Greasy Fork

Greasy Fork is available in English.

增强思否 (SegmentFault) 前端体验

对思否社区的样式进行细节上的改善,支持 Chrome 77 及以上版本的浏览器。这是整合了问答和博客以及样式调整的脚本。

当前为 2022-08-18 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         增强思否 (SegmentFault) 前端体验
// @namespace    https://segmentfault.com/u/jamesfancy
// @version      1.0.8
// @description  对思否社区的样式进行细节上的改善,支持 Chrome 77 及以上版本的浏览器。这是整合了问答和博客以及样式调整的脚本。
// @author       James Fan
// @license      MulanPSL-2.0
// @match        https://segmentfault.com/*
// @icon         https://cdn.segmentfault.com/r-e5cb5889/favicon.ico
// @grant        none
// ==/UserScript==

(() => {
  // src/util/functions.js
  function warn(...args) {
    var _a;
    ((_a = console.warn) != null ? _a : console.log)(...args);
  }

  // src/util/wait.js
  async function waitObject(getter, timeoutSeconds = 0, interval = 200) {
    const timeout = (timeoutSeconds || 0) * 1e3;
    return new Promise((resolve, reject) => {
      const startTime = Date.now();
      let errorCount = 0;
      const timer = setInterval(async () => {
        const result = await (async () => getter())().catch(() => (errorCount++, void 0));
        if (result != null ? result : false) {
          clearInterval(timer);
          resolve(result);
          return;
        }
        if (errorCount > 100) {
          clearInterval(timer);
          reject({ type: "too more error" });
        } else if (timeout && Date.now() - startTime > timeout) {
          clearInterval(timer);
          reject({ type: "timeout", seconds: timeoutSeconds });
        }
      }, interval);
    });
  }
  function warnWaitError(message) {
    return (err) => {
      warn(`[${err.type}]`, message);
      warn(err);
    };
  }

  // src/answer/paste-link.js
  async function injectToPasteLink() {
    var _a;
    if (!navigator.clipboard) {
      ((_a = console.warn) != null ? _a : console.log)("Clipboard API is not supported.");
    }
    const editor = await waitObject(() => {
      var _a2;
      return (_a2 = document.querySelector(".CodeMirror")) == null ? void 0 : _a2.CodeMirror;
    });
    editor.on("paste", async (cm, e) => {
      const md = getLinkMarkdown(e);
      if (md) {
        e.preventDefault();
        const doc = cm.getDoc();
        doc.replaceSelection(md);
      }
    });
    function getLinkMarkdown(e) {
      const data = e.clipboardData;
      const html = data.getData("text/html");
      const div = document.createElement("div");
      div.innerHTML = html;
      if (div.childElementCount !== 1) {
        return;
      }
      const a = div.children[0];
      if (a.tagName !== "A") {
        return;
      }
      return `[${a.innerText}](${a.href})`;
    }
  }

  // src/answer/reply-button.js
  async function moveReplyButtonUp() {
    const [replyArea, preview, buttons] = await waitObject(
      () => {
        const preview2 = document.getElementById("editor-preview-wrap");
        if (!preview2) {
          return;
        }
        const buttons2 = preview2.nextElementSibling;
        if (!buttons2) {
          return;
        }
        const replyArea2 = preview2.parentElement;
        return [replyArea2, preview2, buttons2];
      }
    );
    replyArea.insertBefore(buttons, preview);
    buttons.classList.remove("mt-3");
    buttons.classList.add("mb-3");
  }

  // src/answer/tags.js
  async function moveTagsUp() {
    const [context, info, tags] = await waitObject(() => {
      const context2 = document.querySelector(".introduction-wrap .card-body");
      if (!context2) {
        return;
      }
      const article = context2.querySelector("article");
      const info2 = article == null ? void 0 : article.previousElementSibling;
      if (!(info2 == null ? void 0 : info2.classList.contains("information"))) {
        return;
      }
      if (context2.children[1] !== info2) {
        return;
      }
      const tags2 = context2.querySelector("article").nextElementSibling;
      if (!(tags2 == null ? void 0 : tags2.querySelector("a.badge-tag"))) {
        return;
      }
      return [context2, info2, tags2];
    }, 5);
    context.insertBefore(tags, info.nextElementSibling);
  }

  // src/util/editor/index.js
  function getCodeMirror() {
    var _a;
    return (_a = document.querySelector(".CodeMirror")) == null ? void 0 : _a.CodeMirror;
  }

  // src/util/editor/answer.js
  async function waitAnswerEditorWrapper() {
    return await waitObject(() => document.querySelector(".sf-editor-wrap"));
  }

  // src/answer/add-tail.js
  function addTailToEditor(text) {
    const content = `

---

> ${text}
`;
    const editor = getCodeMirror();
    if (!editor) {
      return;
    }
    const doc = editor.getDoc();
    const pos = { line: editor.lineCount() };
    doc.replaceRange(content, pos);
  }
  function createIcon(...classList) {
    if (!(classList == null ? void 0 : classList.length)) {
      classList = ["fa-solid", "fa-file-signature"];
    }
    const icon = document.createElement("i");
    icon.classList.add(...classList);
    return icon;
  }
  function createImageIcon(url) {
    const img = document.createElement("img");
    img.src = url;
    img.width = "100%";
    img.style.objectFit = "cover";
    img.style.position = "center";
    return img;
  }
  function getIconCreator(icon) {
    switch (typeof icon) {
      case "string":
        if (icon.includes("/")) {
          return () => createImageIcon(icon);
        } else {
          return () => createIcon(icon.split(","));
        }
      case "function":
        return icon;
      default:
        if (Array.isArray(icon)) {
          return () => createIcon(...icon);
        }
        return createIcon;
    }
  }
  function createIconButton(icon, fn) {
    const button = document.createElement("button");
    button.type = "button";
    button.classList.add("p-0", "b-0", "toolbar");
    button.title = "\u6DFB\u52A0\u5341\u5468\u5E74\u300C\u95EE\u7B54\u300D\u6D3B\u52A8\u5C0F\u5C3E\u5DF4";
    Object.assign(button.style, {
      background: "none",
      color: "#e44d26"
    });
    button.appendChild(getIconCreator(icon)());
    button.addEventListener("click", fn);
    const div = document.createElement("div");
    div.classList.add("toolbar-item-wrap");
    div.appendChild(button);
    return div;
  }
  async function addAnswerTail(text, icon) {
    const editorWrap = await waitAnswerEditorWrapper();
    const toolbar = editorWrap.querySelector(".toolbar-wrap");
    const lastChild = toolbar.children[toolbar.children.length - 1];
    toolbar.insertBefore(
      (() => {
        const div = document.createElement("div");
        div.classList.add("toolbar-divider");
        return div;
      })(),
      lastChild
    );
    toolbar.insertBefore(createIconButton(icon, () => addTailToEditor(text)), lastChild);
  }

  // src/answer/index.js
  function answer_default() {
    moveTagsUp().catch(warnWaitError("wait tags elements failed"));
    moveReplyButtonUp().catch(warnWaitError("wait reply button failed"));
    injectToPasteLink().catch(warnWaitError("wait editor failed"));
    addAnswerTail("\u5DF2\u53C2\u4E0E [\u300C\u6781\u5BA2\u89C2\u70B9\u300D](https://segmentfault.com/a/1190000042331835) \uFF0C\u6B22\u8FCE\u6B63\u5728\u9605\u8BFB\u7684\u4F60\u4E5F\u52A0\u5165\u3002").catch(warnWaitError("wait answer editor failed"));
  }

  // src/styles/styles.json
  var styles_default = {
    ".fmt": {
      h6: {
        "font-weight": "bold",
        "&::before": {
          content: '"\u{1F4D1}"'
        }
      }
    },
    kbd: {
      "margin-left": "0.2rem",
      "margin-right": "0.2rem",
      background: "#e5f4ef",
      color: "#333333",
      border: "1px solid #00965e",
      "border-bottom": "2px solid #008050",
      "border-right": "2px solid #008050"
    },
    "#questionMain": {
      ".introduction-wrap": {
        "> .card-body": {
          "h1+div+div": {
            "margin-left": "-1.875rem",
            "margin-right": "-1.875rem",
            padding: "0.5rem 1.875rem",
            background: "rgba(0,150,94,.1)",
            "a.badge-tag": {
              background: "transparent"
            }
          }
        }
      }
    }
  };

  // src/styles/stringify.js
  function toStyleList(styles, selector) {
    const entries = Object.entries(styles);
    const attrEntries = entries.filter(([, value]) => typeof value !== "object");
    const currentStyle = attrEntries.length ? `${selector} { ${attrEntries.map(([key, value]) => `${key}: ${value}`).join("; ")} }` : null;
    const subEntries = entries.filter(([, value]) => typeof value === "object").flatMap(([key, value]) => toStyleList(value, mergeKey(selector, key)));
    if (currentStyle) {
      subEntries.unshift(currentStyle);
    }
    return subEntries;
  }
  function mergeKey(parent, key) {
    if (!parent) {
      return key;
    }
    if (key.startsWith("&")) {
      return `${parent}${key.substring(1)}`;
    }
    return `${parent} ${key}`;
  }
  function toStyleString(styles) {
    return toStyleList(styles).join("\n");
  }

  // src/styles/index.js
  function styles_default2() {
    const styleEl = document.createElement("style");
    styleEl.setAttribute("type", "text/css");
    styleEl.innerText = toStyleString(styles_default);
    document.head.appendChild(styleEl);
  }

  // src/customize-sifou.js
  var policies = [
    ["/q/", answer_default, "segmentfault.com/q/: improve answer"],
    [, styles_default2, "global: improve styles"]
  ].map(([rule, ...rest]) => {
    switch (typeof rule) {
      case "function":
        return [rule, ...rest];
      case "string":
        return [
          () => window.location.pathname.startsWith(rule),
          ...rest
        ];
      case "boolean":
        return [() => !!rule, ...rest];
      case "undefined":
        return [() => true, ...rest];
    }
  });
  policies.filter(([rule]) => rule()).forEach(([, fn, info]) => {
    var _a;
    ((_a = console.info) != null ? _a : console.log)("[SF-MONKEY]", info);
    return fn();
  });
})();
// @license      MulanPSL-2.0