Greasy Fork is available in English.

Discourse Pro

增强 Discourse 论坛。

ติดตั้งสคริปต์นี้?
สคริปต์ที่แนะนำของผู้เขียน

คุณอาจชื่นชอบ 技术远离政治

ติดตั้งสคริปต์นี้
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 545:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {


// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  A: () => (/* binding */ Options)
});

// EXTERNAL MODULE: ./utils/src/gm/Store.ts
var Store = __webpack_require__(915);
;// CONCATENATED MODULE: ./utils/src/gm/MenuCmd.ts
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
 * 选项菜单
 */
var MenuCmd = /*#__PURE__*/function () {
  function MenuCmd() {
    _classCallCheck(this, MenuCmd);
  }
  return _createClass(MenuCmd, null, [{
    key: "register",
    value:
    /**
     * 注册
     * @param name 名称
     * @param fn 点击菜单时执行的函数
     */
    function register(name, fn) {
      return GM_registerMenuCommand(name, fn);
    }

    /**
     * 注销
     * @param menuCmdId 注册时返回的 ID
     */
  }, {
    key: "unregister",
    value: function unregister(menuCmdId) {
      GM_unregisterMenuCommand(menuCmdId);
    }
  }]);
}();

;// CONCATENATED MODULE: ./utils/src/CommonOptions.ts
function CommonOptions_typeof(o) { "@babel/helpers - typeof"; return CommonOptions_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, CommonOptions_typeof(o); }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function CommonOptions_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function CommonOptions_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, CommonOptions_toPropertyKey(descriptor.key), descriptor); } }
function CommonOptions_createClass(Constructor, protoProps, staticProps) { if (protoProps) CommonOptions_defineProperties(Constructor.prototype, protoProps); if (staticProps) CommonOptions_defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function CommonOptions_toPropertyKey(t) { var i = CommonOptions_toPrimitive(t, "string"); return "symbol" == CommonOptions_typeof(i) ? i : i + ""; }
function CommonOptions_toPrimitive(t, r) { if ("object" != CommonOptions_typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != CommonOptions_typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }



/**
 * 选项菜单
 */
var CommonOptions = /*#__PURE__*/function () {
  function CommonOptions() {
    CommonOptions_classCallCheck(this, CommonOptions);
  }
  return CommonOptions_createClass(CommonOptions, null, [{
    key: "registerBoolOption",
    value:
    /**
     * 注册 bool 类型的选项
     *
     * @param option 选项
     */
    function registerBoolOption(option) {
      var _this = this;
      var val = option.value,
        valIsBool = typeof val === 'boolean';
      if (!valIsBool) {
        return;
      }
      // 注册选项和选项点击事件
      var currentMenuCmdId = MenuCmd.register((val ? '✅ ' : '🔲 ') + option.label, function () {
        // 点击后取反
        option.value = !option.value;
        Store/* default */.A.set(option.name, JSON.stringify(option));

        // 重新注册
        MenuCmd.unregister(currentMenuCmdId);
        _this.registerBoolOption(option);
        // 刷新页面
        window.location.reload();
      });

      // 保存选项 ID
      option.menuCmdId = currentMenuCmdId;
      Store/* default */.A.set(option.name, JSON.stringify(option));
    }

    /**
     * 注册所有选项
     *
     * @param options 选项
     * @param moreOptionsUrl 更多设置页面 URL
     */
  }, {
    key: "registerAll",
    value: function registerAll(options, moreOptionsUrl) {
      // 注册“更多设置”选项,点击后打开新页面
      MenuCmd.register('更多设置', function () {
        window.open(moreOptionsUrl, '_blank');
      });
      var _iterator = _createForOfIteratorHelper(options),
        _step;
      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var option = _step.value;
          // TODO 【调试】不保留选项的值,每次都从 Store 中获取
          // Store.set(option.name, null);

          var storeOption = Store/* default */.A.get(option.name) ? JSON.parse(Store/* default */.A.get(option.name)) : null;
          // 如果选项不存在 || 版本不一致 时重置选项
          if (storeOption === null || !storeOption['version'] || storeOption['version'] < option.version) {
            Store/* default */.A.set(option.name, JSON.stringify(option));
            storeOption = option;
          }
          this.registerBoolOption(storeOption);
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
    }

    /**
     * 在 Greasy Fork 脚本详情页中加载选项
     *
     * @param scriptId 脚本 ID
     * @param loadOptionContentFn 加载选项内容的函数
     */
  }, {
    key: "loadInGreasyfork",
    value: function loadInGreasyfork(scriptId, loadOptionContentFn) {
      // 非脚本详情页结束
      if (location.host !== 'greasyfork.org' || location.href.indexOf('/scripts/' + scriptId) == -1) {
        return;
      }
      var selector = {
        scriptLinks: '#script-links',
        scriptOptions: '#script-options',
        scriptContent: '#script-content'
      };
      var $body = $(document.body),
        $scriptLinks = $(selector.scriptLinks),
        $scriptContent = $(selector.scriptContent);

      // 添加“脚本设置”选项卡和点击事件
      $scriptLinks.children('li:eq(0)').after("<li><a href=\"javascript:;\" id=\"script-options\">\u811A\u672C\u8BBE\u7F6E</a></li>");
      $body.on('click', selector.scriptOptions, function () {
        // 移除其他已选中选项的样式
        var $currentLi = $scriptLinks.children('li.current');
        $currentLi.html("<a href=\"".concat(location.href, "\">").concat($currentLi.text(), "</a>"));
        $currentLi.removeClass('current');
        // 给“脚本设置”选项卡添加选中选项的样式
        var $scriptOptions = $(selector.scriptOptions);
        $scriptOptions.parent().addClass('current');
        loadOptionContentFn($scriptContent);
      });
    }
  }]);
}();

;// CONCATENATED MODULE: ./discourse-pro/src/Options.ts
var _Options;
function Options_typeof(o) { "@babel/helpers - typeof"; return Options_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, Options_typeof(o); }
function Options_createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = Options_unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function Options_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return Options_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return Options_arrayLikeToArray(o, minLen); }
function Options_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function Options_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function Options_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, Options_toPropertyKey(descriptor.key), descriptor); } }
function Options_createClass(Constructor, protoProps, staticProps) { if (protoProps) Options_defineProperties(Constructor.prototype, protoProps); if (staticProps) Options_defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _defineProperty(obj, key, value) { key = Options_toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function Options_toPropertyKey(t) { var i = Options_toPrimitive(t, "string"); return "symbol" == Options_typeof(i) ? i : i + ""; }
function Options_toPrimitive(t, r) { if ("object" != Options_typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != Options_typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }



var Options = /*#__PURE__*/function () {
  function Options() {
    Options_classCallCheck(this, Options);
  }
  return Options_createClass(Options, null, [{
    key: "registerBoolOption",
    value:
    /**
     * 注册 bool 类型的选项
     * @param option 选项
     */
    function registerBoolOption(option) {
      CommonOptions.registerBoolOption(option);
    }

    /**
     * 注册所有选项
     */
  }, {
    key: "registerAll",
    value: function registerAll() {
      CommonOptions.registerAll(this.options, 'https://greasyfork.org/scripts/' + this.SCRIPT_ID);
    }
  }, {
    key: "onChangByBoolOption",
    value: function onChangByBoolOption(key) {
      var _this = this;
      var optionSelector = '#script-options-' + key;
      $(document.body).on('change', optionSelector, function () {
        var option = JSON.parse(Store/* default */.A.get(key));
        option.value = !option.value;
        // 重新注册选项
        MenuCmd.unregister(option.menuCmdId);
        _this.registerBoolOption(option);
      });
    }

    /**
     * 在页面中加载选项
     */
  }, {
    key: "loadInGreasyfork",
    value: function loadInGreasyfork() {
      var _this2 = this;
      CommonOptions.loadInGreasyfork(this.SCRIPT_ID, function ($scriptContent) {
        // 添加脚本设置的内容
        var scriptContent = '';
        var _iterator = Options_createForOfIteratorHelper(_this2.options),
          _step;
        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var option = _step.value;
            var storeOption = JSON.parse(Store/* default */.A.get(option.name)),
              optionName = storeOption.name,
              optionVal = storeOption.value;
            scriptContent += "<h3>".concat(option.label, "</h3>");
            switch (optionName) {
              case _this2.Keys.dragBar:
                scriptContent += "<label><input type=\"checkbox\" id=\"script-options-".concat(optionName, "\" ").concat(optionVal ? 'checked' : '', "> \u4FA7\u8FB9\u680F\u62D6\u62FD\u6761\uFF08\u4FA7\u8FB9\u680F\u548C\u4E3B\u5185\u5BB9\u95F4\u6DFB\u52A0\u62D6\u62FD\u6761\uFF0C\u7528\u4E8E\u8C03\u6574\u4E24\u8005\u5BBD\u5EA6\uFF09</label>");
                break;
              case _this2.Keys.widescreenMode:
                scriptContent += "<label><input type=\"checkbox\" id=\"script-options-".concat(optionName, "\" ").concat(optionVal ? 'checked' : '', "> \u5BBD\u5C4F\u6A21\u5F0F</label>");
                break;
            }
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
        $scriptContent.html(scriptContent);

        // 侧边栏拖拽条
        _this2.onChangByBoolOption(_this2.Keys.dragBar);
        // 宽屏模式
        _this2.onChangByBoolOption(_this2.Keys.widescreenMode);
      });
    }
  }]);
}();
_Options = Options;
_defineProperty(Options, "SCRIPT_ID", 520817);
/**
 * 选项 Key
 */
_defineProperty(Options, "Keys", {
  dragBar: 'dragBar',
  widescreenMode: 'widescreenMode'
});
/**
 * 选项
 * @private
 */
_defineProperty(Options, "options", [{
  label: '侧边栏拖拽条',
  name: _Options.Keys.dragBar,
  version: 1,
  value: false,
  menuCmdId: null
}, {
  label: '宽屏模式',
  name: _Options.Keys.widescreenMode,
  version: 1,
  value: false,
  menuCmdId: null,
  token: ''
}]);


/***/ }),

/***/ 150:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {


// EXTERNAL MODULE: ./utils/src/gm/Store.ts
var Store = __webpack_require__(915);
;// CONCATENATED MODULE: ./discourse-pro/src/module/widescreenMode.ts
/**
 * 添加 history 的 pushState 和 replaceState 事件
 *
 * 参考:https://segmentfault.com/a/1190000017560688#item-4
 */
function addPushReplaceStateEvent() {
  var _wr = function _wr(type) {
    var orig = history[type];
    return function () {
      var rv = orig.apply(this, arguments);
      var e = new Event(type);
      // @ts-ignore
      e.arguments = arguments;
      window.dispatchEvent(e);
      return rv;
    };
  };
  history.pushState = _wr('pushState');
  history.replaceState = _wr('replaceState');
}

/**
 * 加载宽屏模式
 * @param options
 */
function loadWidescreenMode(options) {
  addPushReplaceStateEvent();
  var headerWrap = options.headerWrap,
    mainOutletWrapper = options.mainOutletWrapper,
    mainOutlet = options.mainOutlet,
    postStream = options.postStream;
  var $headerWrap = $(headerWrap),
    $mainOutletWrapper = $(mainOutletWrapper),
    $mainOutlet = $(mainOutlet),
    $postStream = $(postStream);

  // 顶部撑满
  $headerWrap.css('max-width', '100%');
  // 侧边栏和主内容撑满
  $mainOutletWrapper.css('max-width', '100%');
  // 主内容撑满
  $mainOutlet.css('width', '100%');

  // console.debug('话题页首次加载宽屏模式 + 监听话题列表变化')
  // 话题页首次加载宽屏模式 + 监听话题列表变化
  loadWidescreenModeByTopicAndObserver(options, $postStream);

  // 历史记录变化时话题页重新加载宽屏模式
  window.addEventListener('popstate', function () {
    // console.debug('历史记录变化时话题页重新加载宽屏模式')
    popstateAndPushStateListener(postStream, options, $mainOutlet);
  });
  // 单页面 pushState 切换页面时话题页重新加载宽屏模式
  window.addEventListener('pushState', function () {
    // console.debug('单页面 pushState 切换页面时话题页重新加载宽屏模式')
    popstateAndPushStateListener(postStream, options, $mainOutlet);
  });
  window.addEventListener('replaceState', function () {
    // console.debug('单页面 replaceState 切换页面时话题页重新加载宽屏模式')
    popstateAndPushStateListener(postStream, options, $mainOutlet);
  });
}

/**
 * popstate 和 pushState 事件监听
 * @param postStreamSelector 话题内容选择器
 * @param options 选项
 * @param $mainOutlet 主内容
 */
function popstateAndPushStateListener(postStreamSelector, options, $mainOutlet) {
  if (location.href.indexOf('/topic/') !== -1) {
    // 等待 .post-stream 加载完成
    var interval = setInterval(function () {
      var $newPostStreamWrapper = $(postStreamSelector);
      if ($newPostStreamWrapper.length > 0) {
        clearInterval(interval);
        loadWidescreenModeByTopicAndObserver(options, $(postStreamSelector));
      }
    }, 500);
  }
}

/**
 * 话题页加载宽屏模式 + 监听话题内容变化
 * @param options 选项
 * @param $postStream 话题内容
 */
function loadWidescreenModeByTopicAndObserver(options, $postStream) {
  // 监听话题列表变化
  if (location.href.indexOf('/topic/') == -1) {
    return;
  }
  loadWidescreenModeByTopic(options);
  if ($postStream.data('hasObserver')) {
    // console.debug('[discourse-pro-widescreenMode] 已存在话题内容变化监听器,跳过');
    return;
  }

  // 防抖函数
  var debounceTimeout;
  var debounce = function debounce(func, delay) {
    clearTimeout(debounceTimeout);
    debounceTimeout = setTimeout(func, delay);
  };
  var observer = new MutationObserver(function (mutationsList) {
    debounce(function () {
      loadWidescreenModeByTopic(options);
    }, 1000);
  });

  // 是否已监听
  $postStream.data('hasObserver', true);
  // 此处监听 .posts-wrapper 下的所有节点而不是 .post-stream 下的子节点,因为 .post-stream 会在时间轴跳动后重新加载
  observer.observe($postStream[0], {
    // 监听子节点
    childList: true,
    // 不监听子节点下的节点
    subtree: false
  });
}

/**
 * 话题页加载宽屏模式
 * @param options
 */
function loadWidescreenModeByTopic(options) {
  var postStream = options.postStream,
    topicAvatar = options.topicAvatar,
    topicBody = options.topicBody,
    topicMap = options.topicMap,
    loadingContainer = options.loadingContainer,
    topicTimerInfo = options.topicTimerInfo,
    topicFooterBtns = options.topicFooterBtns,
    moreTopicsContainer = options.moreTopicsContainer;
  var $postStream = $(postStream),
    $topicAvatar = $(topicAvatar),
    $topicBody = $(topicBody),
    $topicMap = $(topicMap),
    $loadingContainer = $(loadingContainer),
    $topicTimerInfo = $(topicTimerInfo),
    $topicFooterBtns = $(topicFooterBtns),
    $moreTopicsContainer = $(moreTopicsContainer);
  var postStreamWidth = $postStream.width();
  var topicAvatarWidth = $topicAvatar.width();
  var topicWidth = postStreamWidth - 45;
  var topicBodyWidth = topicWidth - topicAvatarWidth + 'px';

  // 如果第一个的宽度和最后一个的宽度不一样,说明话题列表变化了
  var firstTopicBodyWidth = $($topicBody[0]).css('width');
  var lastTopicBodyWidth = $($topicBody[$topicBody.length - 1]).css('width');
  if (firstTopicBodyWidth == lastTopicBodyWidth && firstTopicBodyWidth == topicBodyWidth) {
    // console.debug('[discourse-pro-widescreenMode] 话题页加载宽屏模式已加载过,跳过');
    return;
  }

  // 话题内容撑满
  $topicBody.css('width', topicBodyWidth);
  // 话题主内容后浏览量、链接、回复人等信息撑满
  $topicMap.css('max-width', topicWidth + 'px');
  // 最后一个回复后的底边框撑满
  $loadingContainer.css('width', topicWidth + 'px');
  $topicTimerInfo.css('max-width', topicWidth + 'px');
  // 话题底部按钮撑满
  $topicFooterBtns.css('max-width', topicWidth + 'px');
  // 更多话题列表撑满
  $moreTopicsContainer.css('max-width', topicWidth + 'px');
}

;// CONCATENATED MODULE: ./discourse-pro/src/module/dragBar.ts


function loadDragBar(options) {
  var mainOutletWrapper = options.mainOutletWrapper,
    sidebarWrapper = options.sidebarWrapper,
    sidebar = options.sidebar,
    headerSidebarToggleBtn = options.headerSidebarToggleBtn,
    sidebarWidthKey = options.sidebarWidthKey,
    minSidebarWidth = options.minSidebarWidth,
    maxSidebarWidth = options.maxSidebarWidth;
  var $mainOutletWrapper = $(mainOutletWrapper),
    $sidebarWrapper = $(sidebarWrapper),
    $sidebar = $(sidebar),
    $headerSidebarToggleBtn = $(headerSidebarToggleBtn);

  // 侧边栏是否存在
  var sidebarExist = $sidebar.length > 0;
  if (sidebarExist) {
    // 读取存储的侧边栏宽度
    var storeSidebarWidth = Store/* default */.A.get(sidebarWidthKey);
    if (storeSidebarWidth) {
      $mainOutletWrapper.css('grid-template-columns', "".concat(storeSidebarWidth, "px minmax(0, 1fr)"));
    }
  }

  // 在侧边栏内部追加一个拖拽条
  $sidebarWrapper.append("\n    <div class=\"drag-bar\" style=\"width: 4px; cursor: ew-resize\"></div>\n  ");

  // 拖拽条
  var $dragBar = $sidebarWrapper.find('.drag-bar');
  // 是否正在拖拽
  var isDragging = false;
  // 鼠标按下时的 clientX
  var startClientX = 0;
  // 鼠标按下时的侧边栏宽度
  var startSidebarWidth = 0;
  // 侧边栏新宽度
  var newSidebarWidth = 0;

  // 鼠标按下事件
  $dragBar.on('mousedown', function (e) {
    startClientX = e.clientX;
    startSidebarWidth = $sidebarWrapper.width() || 0;
    isDragging = true;
    // 改变鼠标样式
    document.body.style.cursor = 'ew-resize';
    // 设置拖拽条背景色
    $dragBar.css('background-color', '#e6e6e6');
    // 防止文本被选中
    e.preventDefault();
  });

  // 鼠标移动事件
  $(document).on('mousemove', function (e) {
    if (!isDragging) return;

    // 计算新的宽度
    var deltaX = e.clientX - startClientX;
    newSidebarWidth = Math.min(maxSidebarWidth, Math.max(minSidebarWidth, startSidebarWidth + deltaX));
    $mainOutletWrapper.css('grid-template-columns', "".concat(newSidebarWidth, "px minmax(0, 1fr)"));
    loadWidescreenModeByTopic(options);
  });

  // 鼠标松开事件
  $(document).on('mouseup', function () {
    if (!isDragging) return;
    isDragging = false;
    // 恢复鼠标样式
    document.body.style.cursor = 'default';
    // 恢复拖拽条背景色
    $dragBar.css('background-color', 'transparent');
    // 记忆侧边栏宽度
    Store/* default */.A.set(sidebarWidthKey, newSidebarWidth);
  });

  // 展开收起侧边栏按钮点击事件
  $headerSidebarToggleBtn.on('click', function () {
    sidebarExist = !sidebarExist;
    $mainOutletWrapper.css('grid-template-columns', "".concat(sidebarExist ? Store/* default */.A.get(sidebarWidthKey) + 'px' : '0', " minmax(0, 1fr)"));
  });
}
// EXTERNAL MODULE: ./discourse-pro/src/Options.ts + 2 modules
var Options = __webpack_require__(545);
;// CONCATENATED MODULE: ./discourse-pro/src/main.ts
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
// ==UserScript==
// @name         Discourse Pro
// @namespace    http://tampermonkey.net/
// @version      0.1.3
// @description  增强 Discourse 论坛。
// @author       duanluan
// @copyright    2024, duanluan (https://github.com/duanluan)
// @license      Apache-2.0; https://www.apache.org/licenses/LICENSE-2.0.txt
// @homepage     https://greasyfork.org/zh-CN/scripts/520817
// @supportURL   https://github.com/duanluan/tampermonkey-scripts/issues
// @match        *://greasyfork.org/*
// @match        *://linux.do/*
// @match        *://meta.appinn.net/*
// @require      https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.slim.min.js
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// ==/UserScript==

// ==OpenUserJS==
// @author       duanluan
// @updateURL    https://raw.kkgithub.com/duanluan/tampermonkey-scripts/main/discourse-pro/dist/discourse-pro.user.js
// ==/OpenUserJS==





(function (_$) {
  'use strict';

  Options/* default */.A.registerAll();
  Options/* default */.A.loadInGreasyfork();

  // 判断是否为 Discourse
  var generator = (_$ = $('meta[name="generator"]')) === null || _$ === void 0 ? void 0 : _$.attr('content');
  if (!generator || generator.indexOf('Discourse') == -1) return;
  var selector = {
    headerWrap: '.d-header>.wrap',
    // 侧边栏展开收起按钮
    headerSidebarToggleBtn: '.header-sidebar-toggle>button',
    // 侧边栏和主内容的父容器
    mainOutletWrapper: '#main-outlet-wrapper',
    // 侧边栏
    sidebarWrapper: '.sidebar-wrapper',
    sidebar: '#d-sidebar',
    // 主内容
    mainOutlet: '#main-outlet',
    // 话题内容父容器
    postStream: '.post-stream',
    // 话题头像
    topicAvatar: '.topic-avatar',
    // 话题内容
    topicBody: '.topic-body',
    // 话题主内容后浏览量、链接、回复人等信息
    topicMap: '.topic-map',
    // 最后一个回复后的底边框
    loadingContainer: '.loading-container',
    topicTimerInfo: '.topic-timer-info',
    // 话题底部按钮
    topicFooterBtns: '#topic-footer-buttons',
    // 更多话题列表
    moreTopicsContainer: '.more-topics__container'
  };
  var storeKeys = {
    // 侧边栏宽度
    sidebarWidth: 'sidebarWidth_'
  };

  // 加载拖拽条
  if (JSON.parse(Store/* default */.A.get(Options/* default */.A.Keys.dragBar)).value) {
    loadDragBar(_objectSpread(_objectSpread({}, selector), {}, {
      sidebarWidthKey: storeKeys.sidebarWidth + location.host,
      minSidebarWidth: 180,
      maxSidebarWidth: 500
    }));
  }
  // 加载宽屏模式
  if (JSON.parse(Store/* default */.A.get(Options/* default */.A.Keys.widescreenMode)).value) {
    loadWidescreenMode(_objectSpread({}, selector));
  }
})();

/***/ }),

/***/ 915:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   A: () => (/* binding */ Store)
/* harmony export */ });
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
 * 存储
 */
var Store = /*#__PURE__*/function () {
  function Store() {
    _classCallCheck(this, Store);
  }
  return _createClass(Store, null, [{
    key: "get",
    value:
    /**
     * 获取
     * @param key 键
     */
    function get(key) {
      return GM_getValue(key);
    }

    /**
     * 设置
     * @param key 键
     * @param value 值
     */
  }, {
    key: "set",
    value: function set(key, value) {
      GM_setValue(key, value);
    }
  }]);
}();


/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module is referenced by other modules so it can't be inlined
/******/ 	__webpack_require__(545);
/******/ 	var __webpack_exports__ = __webpack_require__(150);
/******/ 	
/******/ })()
;
//# sourceMappingURL=discourse-pro.user.js.map