跳转到内容

User:Ericliu1912/維基專題評級工具/rater app.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/***************************************************************************************************
 Rater --- by Evad37
 > Helps assess WikiProject banners.

 This script is a loader that will load the actual script from the /app.js subpage
 once Resource loader modules are loaded and the page DOM is ready.
 Source code is available at https://github.com/evad37/rater
***************************************************************************************************/
// <nowiki>
$.when(
	// Resource loader modules
	mw.loader.using([
		"mediawiki.util", "mediawiki.api", "mediawiki.Title",
		"oojs-ui-core", "oojs-ui-widgets", "oojs-ui-windows",
		"oojs-ui.styles.icons-content", "oojs-ui.styles.icons-interactions",
		"oojs-ui.styles.icons-moderation", "oojs-ui.styles.icons-editing-core",
		"mediawiki.widgets", "mediawiki.widgets.NamespacesMultiselectWidget",
	]),
	// Page ready
	$.ready
).then(function() {
	var conf = mw.config.get(["wgNamespaceNumber", "wgPageName"]);
	// Do not operate on Special: pages, nor on non-existent pages or their talk pages
	if ( conf.wgNamespaceNumber < 0 || $("li.new[id|=ca-nstab]").length ) {
		return;
	}
	// Do not operate on top-level User and User_talk pages (only on subpages)
	if (
		conf.wgNamespaceNumber >= 2 &&
		conf.wgNamespaceNumber <= 3 &&
		conf.wgPageName.indexOf("/") === -1
	) {
		return;
	}
	(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
module.exports={
  "name": "rater_zhwiki",
  "version": "1.2",
  "description": "協助維基專題評級的維基百科使用者指令碼",
  "homepage": "https://github.com/yfdyh000/rater_zhwiki",
  "browser": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint:es5": "jshint index.js",
    "lint:es6": "eslint index.js \"rater-src/**\"",
    "lint:fix": "eslint index.js \"rater-src/**\" --fix",
    "lint": "npm run lint:es6 && npm run lint:es5",
    "build:bundle": "browserify rater-src/App.js --debug -t babelify --outfile dist/rater.js",
    "build:minify": "uglifyjs dist/rater.js --compress -b ascii_only=true,beautify=false --output dist/rater.min.js",
    "build:concat": "node ./index_warper.mjs commenttomin",
    "build:dev": "npm run lint && npm run build:bundle && npm run build:dev_concat && npm run build:dev_pub",
    "build:dev_concat": "node ./index_warper.mjs",
    "build:dev_pub": "node ./index_warper.mjs pub",
    "build": "npm run lint && npm run build:bundle && npm run build:minify && npm run build:concat",
    "watch-build": "nodemon --watch rater-src --watch index_warper.mjs --exec npm run build",
    "watch-dev": "nodemon --watch rater-src --watch index_warper.mjs --exec npm run build:dev"
  },
  "author": {
    "name": "Evad37",
    "url": "https://en.wikipedia.org/wiki/User:Evad37",
    "name": "YFdyh000",
    "url": "https://wiki.zwnes.eu.org/wiki/User:YFdyh000",
    "name": "Ericliu1912",
    "url": "https://wiki.zwnes.eu.org/wiki/User:Ericliu1912"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/yfdyh000/rater_zhwiki.git"
  },
  "license": "(MIT OR CC-BY-4.0)",
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@babel/preset-env": "^7.9.0",
    "babelify": "^10.0.0",
    "browserify": "^16.5.0",
    "concat-cli": "^4.0.0",
    "eslint": "^6.8.0",
    "jshint": "^2.11.0",
    "nodemon": "^2.0.16",
    "uglify-js": "^3.8.0"
  }
}

},{}],2:[function(require,module,exports){
"use strict";

var _setup = _interopRequireDefault(require("./setup"));
var _autostart = _interopRequireDefault(require("./autostart"));
var _css = _interopRequireDefault(require("./css.js"));
var _api = require("./api");
var _windowManager = _interopRequireDefault(require("./windowManager"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

(function App() {
  var stylesheet;
  var showMainWindow = function showMainWindow(data) {
    if (!data || !data.success) {
      return;
    }
    if (stylesheet) {
      stylesheet.disabled = false;
    } else {
      stylesheet = mw.util.addCSS(_css["default"]);
    }
    // Add css class to body to enable background scrolling
    document.getElementsByTagName("body")[0].classList.add("rater-mainWindow-open");
    // Open the window
    _windowManager["default"].openWindow("main", data).closed.then(function (result) {
      // Disable/remove the css styles, so as to not interfere with other scripts/content/OOUI windows
      if (stylesheet) {
        stylesheet.disabled = true;
      }
      document.getElementsByTagName("body")[0].classList.remove("rater-mainWindow-open");
      // Restart if needed
      if (result && result.restart) {
        _windowManager["default"].removeWindows(["main"]).then(_setup["default"]).then(showMainWindow, showSetupError);
        return;
      }
      // Show notification when saved successfully
      if (result && result.success) {
        var $message = $("<span>").append($("<strong>").text(wgULS("评级保存成功。", "成功儲存評級結果。")));
        if (result.upgradedStub) {
          $message.append($("<br>"),
          // TODO: There should be a link that will edit the article for you
          $("<span>").text("注意,条目似乎是一个小作品。"));
        }
        mw.notify($message, {
          autoHide: true,
          autoHideSeconds: "long",
          tag: wgULS("评级已保存", "成功儲存評級")
        });
      }
    });
  };
  var showSetupError = function showSetupError(code, jqxhr) {
    return OO.ui.alert((0, _api.makeErrorMsg)(code, jqxhr), {
      title: wgULS("工具打开失败", "工具無法開啟")
    });
  };

  // Invocation by portlet link 
  if ($("#ca-rater").length === 0) {
    var area = "";
    switch (mw.config.get('skin')) {
      case 'vector':
        area = 'p-views';
        break;
      case 'minerva':
        // Mobile skin
        area = 'p-tb';
        break;
      default:
        area = 'p-cactions';
        break;
    }
    mw.util.addPortletLink(area, "#", wgULS("评级", "評級"), "ca-rater", wgULS("质量和重要度评级", "為頁面評級"), "5");
    $("#ca-rater").click(function (event) {
      event.preventDefault();
      (0, _setup["default"])().then(showMainWindow, showSetupError);
    });
  }

  // Invocation by auto-start (do not show message on error)
  (0, _autostart["default"])().then(showMainWindow);
})();
// </nowiki>

},{"./api":15,"./autostart":16,"./css.js":19,"./setup":22,"./windowManager":24}],3:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getWithRedirectTo = exports.parseTemplates = exports.Template = void 0;
var _api = _interopRequireDefault(require("./api"));
var _util = require("./util");
var _config = _interopRequireDefault(require("./config"));
var cache = _interopRequireWildcard(require("./cache"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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; }
// <nowiki>

/** Template
 *
 * @class
 * Represents the wikitext of template transclusion. Used by #parseTemplates.
 * @prop {String} name Name of the template
 * @prop {String} wikitext Full wikitext of the transclusion
 * @prop {Object[]} parameters Parameters used in the translcusion, in order, of form:
	{
		name: {String|Number} parameter name, or position for unnamed parameters,
		value: {String} Wikitext passed to the parameter (whitespace trimmed),
		wikitext: {String} Full wikitext (including leading pipe, parameter name/equals sign (if applicable), value, and any whitespace)
	}
 * @constructor
 * @param {String} wikitext Wikitext of a template transclusion, starting with '{{' and ending with '}}'.
 */
var Template = function Template(wikitext) {
  this.wikitext = wikitext;
  this.parameters = [];
  // Spacing around pipes, equals signs, end braces (defaults)
  this.pipeStyle = "|";
  this.equalsStyle = "=";
  this.endBracesStyle = "}}";
};
exports.Template = Template;
Template.prototype.addParam = function (name, val, wikitext) {
  this.parameters.push({
    "name": name,
    "value": val,
    "wikitext": "|" + wikitext
  });
};
/**
 * Get a parameter data by parameter name
 */
Template.prototype.getParam = function (paramName) {
  return this.parameters.find(function (p) {
    return p.name == paramName;
  });
};
Template.prototype.setName = function (name) {
  this.name = name.trim();
};
Template.prototype.getTitle = function () {
  return mw.Title.newFromText("Template:" + this.name);
};

/**
 * parseTemplates
 *
 * Parses templates from wikitext.
 * Based on SD0001's version at <https://en.wikipedia.org/wiki/User:SD0001/parseAllTemplates.js>.
 * Returns an array containing the template details:
 *  var templates = parseTemplates("Hello {{foo |Bar|baz=qux |2=loremipsum|3=}} world");
 *  console.log(templates[0]); // --> object
	{
		name: "foo",
		wikitext:"{{foo |Bar|baz=qux | 2 = loremipsum  |3=}}",
		parameters: [
			{
				name: 1,
				value: 'Bar',
				wikitext: '|Bar'
			},
			{
				name: 'baz',
				value: 'qux',
				wikitext: '|baz=qux '
			},
			{
				name: '2',
				value: 'loremipsum',
				wikitext: '| 2 = loremipsum  '
			},
			{
				name: '3',
				value: '',
				wikitext: '|3='
			}
		],
		getParam: function(paramName) {
			return this.parameters.find(function(p) { return p.name == paramName; });
		}
	}
 *    
 * 
 * @param {String} wikitext
 * @param {Boolean} recursive Set to `true` to also parse templates that occur within other templates,
 *  rather than just top-level templates. 
 * @return {Template[]} templates
*/
var parseTemplates = function parseTemplates(wikitext, recursive) {
  /* eslint-disable no-control-regex */
  if (!wikitext) {
    return [];
  }
  var strReplaceAt = function strReplaceAt(string, index, _char) {
    return string.slice(0, index) + _char + string.slice(index + 1);
  };
  var result = [];
  var processTemplateText = function processTemplateText(startIdx, endIdx) {
    var text = wikitext.slice(startIdx, endIdx);
    var template = new Template("{{" + text.replace(/\x01/g, "|") + "}}");

    // swap out pipe in links with \x01 control character
    // [[File: ]] can have multiple pipes, so might need multiple passes
    while (/(\[\[[^\]]*?)\|(.*?\]\])/g.test(text)) {
      text = text.replace(/(\[\[[^\]]*?)\|(.*?\]\])/g, "$1\x01$2");
    }

    // Figure out most-used spacing styles for pipes/equals
    template.pipeStyle = (0, _util.mostFrequent)(text.match(/[\s\n]*\|[\s\n]*/g)) || "|";
    template.equalsStyle = (0, _util.mostFrequent)(text.replace(/(=[^|]*)=+/g, "$1").match(/[\s\n]*=[\s\n]*/g)) || "=";
    // Figure out end-braces style
    var endSpacing = text.match(/[\s\n]*$/);
    template.endBracesStyle = (endSpacing ? endSpacing[0] : "") + "}}";
    var chunks = text.split("|").map(function (chunk) {
      // change '\x01' control characters back to pipes
      return chunk.replace(/\x01/g, "|");
    });
    template.setName(chunks[0]);
    var parameterChunks = chunks.slice(1);
    var unnamedIdx = 1;
    parameterChunks.forEach(function (chunk) {
      var indexOfEqualTo = chunk.indexOf("=");
      var indexOfOpenBraces = chunk.indexOf("{{");
      var isWithoutEquals = !chunk.includes("=");
      var hasBracesBeforeEquals = chunk.includes("{{") && indexOfOpenBraces < indexOfEqualTo;
      var isUnnamedParam = isWithoutEquals || hasBracesBeforeEquals;
      var pName, pNum, pVal;
      if (isUnnamedParam) {
        // Get the next number not already used by either an unnamed parameter, or by a
        // named parameter like `|1=val`
        while (template.getParam(unnamedIdx)) {
          unnamedIdx++;
        }
        pNum = unnamedIdx;
        pVal = chunk.trim();
      } else {
        pName = chunk.slice(0, indexOfEqualTo).trim();
        pVal = chunk.slice(indexOfEqualTo + 1).trim();
      }
      template.addParam(pName || pNum, pVal, chunk);
    });
    result.push(template);
  };
  var n = wikitext.length;

  // number of unclosed braces
  var numUnclosed = 0;

  // are we inside a comment, or between nowiki tags, or in a {{{parameter}}}?
  var inComment = false;
  var inNowiki = false;
  var inParameter = false;
  var startIdx, endIdx;
  for (var i = 0; i < n; i++) {
    if (!inComment && !inNowiki && !inParameter) {
      if (wikitext[i] === "{" && wikitext[i + 1] === "{" && wikitext[i + 2] === "{" && wikitext[i + 3] !== "{") {
        inParameter = true;
        i += 2;
      } else if (wikitext[i] === "{" && wikitext[i + 1] === "{") {
        if (numUnclosed === 0) {
          startIdx = i + 2;
        }
        numUnclosed += 2;
        i++;
      } else if (wikitext[i] === "}" && wikitext[i + 1] === "}") {
        if (numUnclosed === 2) {
          endIdx = i;
          processTemplateText(startIdx, endIdx);
        }
        numUnclosed -= 2;
        i++;
      } else if (wikitext[i] === "|" && numUnclosed > 2) {
        // swap out pipes in nested templates with \x01 character
        wikitext = strReplaceAt(wikitext, i, "\x01");
      } else if (/^<!--/.test(wikitext.slice(i, i + 4))) {
        inComment = true;
        i += 3;
      } else if (/^<nowiki ?>/.test(wikitext.slice(i, i + 9))) {
        inNowiki = true;
        i += 7;
      }
    } else {
      // we are in a comment or nowiki or {{{parameter}}}
      if (wikitext[i] === "|") {
        // swap out pipes with \x01 character
        wikitext = strReplaceAt(wikitext, i, "\x01");
      } else if (/^-->/.test(wikitext.slice(i, i + 3))) {
        inComment = false;
        i += 2;
      } else if (/^<\/nowiki ?>/.test(wikitext.slice(i, i + 10))) {
        inNowiki = false;
        i += 8;
      } else if (wikitext[i] === "}" && wikitext[i + 1] === "}" && wikitext[i + 2] === "}") {
        inParameter = false;
        i += 2;
      }
    }
  }
  if (recursive) {
    var subtemplates = (0, _util.filterAndMap)(result, function (template) {
      return /\{\{(?:.|\n)*\}\}/.test(template.wikitext.slice(2, -2));
    }, function (template) {
      return parseTemplates(template.wikitext.slice(2, -2), true);
    });
    return result.concat.apply(result, subtemplates);
  }
  return result;
}; /* eslint-enable no-control-regex */

/**
 * @param {Template|Template[]} templates
 * @return {Promise<Template>|Promise<Template[]>}
 */
exports.parseTemplates = parseTemplates;
var getWithRedirectTo = function getWithRedirectTo(templates) {
  var templatesArray = Array.isArray(templates) ? templates : [templates];
  if (templatesArray.length === 0) {
    return $.Deferred().resolve([]);
  }
  return _api["default"].get({
    "action": "query",
    "format": "json",
    "titles": (0, _util.filterAndMap)(templatesArray, function (template) {
      return template.getTitle() !== null;
    }, function (template) {
      return template.getTitle().getPrefixedText();
    }),
    "redirects": 1
  }).then(function (result) {
    if (!result || !result.query) {
      return $.Deferred().reject("Empty response");
    }
    if (result.query.redirects) {
      result.query.redirects.forEach(function (redirect) {
        var i = templatesArray.findIndex(function (template) {
          var title = template.getTitle();
          return title && title.getPrefixedText() === redirect.from;
        });
        if (i !== -1) {
          templatesArray[i].redirectTarget = mw.Title.newFromText(redirect.to);
        }
      });
    }
    return Array.isArray(templates) ? templatesArray : templatesArray[0];
  });
};
exports.getWithRedirectTo = getWithRedirectTo;
Template.prototype.getDataForParam = function (key, paraName) {
  if (!this.paramData) {
    return null;
  }
  // If alias, switch from alias to preferred parameter name
  var para = this.paramAliases[paraName] || paraName;
  if (!this.paramData[para]) {
    return;
  }
  var data = this.paramData[para][key];
  // Data might actually be an object with key "en"
  if (data && data.zh && !Array.isArray(data)) {
    return data.zh;
  }
  return data;
};
Template.prototype.isShellTemplate = function () {
  var mainText = this.redirectTarget ? this.redirectTarget.getMainText() : this.getTitle().getMainText();
  return _config["default"].shellTemplates.includes(mainText);
};
Template.prototype.setParamDataAndSuggestions = function () {
  var self = this;
  var paramDataSet = $.Deferred();
  if (self.paramData) {
    return paramDataSet.resolve();
  }
  var prefixedText = self.redirectTarget ? self.redirectTarget.getPrefixedText() : self.getTitle().getPrefixedText();
  var cachedInfo = cache.read(prefixedText + "-params");
  if (cachedInfo && cachedInfo.value && cachedInfo.staleDate && cachedInfo.value.paramData != null && cachedInfo.value.parameterSuggestions != null && cachedInfo.value.paramAliases != null) {
    self.notemplatedata = cachedInfo.value.notemplatedata;
    self.paramData = cachedInfo.value.paramData;
    self.parameterSuggestions = cachedInfo.value.parameterSuggestions;
    self.paramAliases = cachedInfo.value.paramAliases;
    paramDataSet.resolve();
    if (!(0, _util.isAfterDate)(cachedInfo.staleDate)) {
      // Just use the cached data
      return paramDataSet;
    } // else: Use the cache data for now, but also fetch new data from API
  }
  _api["default"].get({
    action: "templatedata",
    titles: prefixedText,
    redirects: 1,
    includeMissingTitles: 1
  }).then(function (response) {
    return response;
  }, function /*error*/ () {
    return null;
  } // Ignore errors, will use default data
  ).then(function (result) {
    // Figure out page id (beacuse action=templatedata doesn't have an indexpageids option)
    var id = result && $.map(result.pages, function (_value, key) {
      return key;
    });
    if (!result || !result.pages[id] || result.pages[id].notemplatedata || !result.pages[id].params) {
      // No TemplateData, so use defaults (guesses)
      self.notemplatedata = true;
      self.templatedataApiError = !result;
      if (new RegExp("WikiProject ", "i").test(prefixedText) || prefixedText.includes("专题") || prefixedText.includes("專題")) self.paramData = _config["default"].defaultParameterData;
    } else {
      // TODO: review for https://wiki.zwnes.eu.org/w/index.php?title=Special:%E6%90%9C%E7%B4%A2&search=rater-data.js&profile=advanced&fulltext=1&ns10=1
      self.paramData = result.pages[id].params;
    }
    self.paramAliases = {};
    $.each(self.paramData, function (paraName, paraData) {
      // Extract aliases for easier reference later on
      if (paraData.aliases && paraData.aliases.length) {
        paraData.aliases.forEach(function (alias) {
          self.paramAliases[alias] = paraName;
        });
      }
      // Extract allowed values array from description
      if (paraData.description && /\[.*'.+?'.*?\]/.test(paraData.description.zh)) {
        try {
          var allowedVals = JSON.parse(paraData.description.zh.replace(/^.*\[/, "[").replace(/"/g, "\\\"").replace(/'/g, "\"").replace(/,\s*]/, "]").replace(/].*$/, "]"));
          self.paramData[paraName].allowedValues = allowedVals;
        } catch (e) {
          console.warn("[Rater] Could not parse allowed values in description:\n  " + paraData.description.zh + "\n Check TemplateData for parameter |" + paraName + "= in " + self.getTitle().getPrefixedText());
        }
      }
    });

    // Make suggestions for combobox
    var allParamsArray = !self.notemplatedata && result.pages[id].paramOrder || $.map(self.paramData, function (_val, key) {
      return key;
    });
    self.parameterSuggestions = allParamsArray.filter(function (paramName) {
      return paramName && paramName !== "class" && paramName !== "importance";
    }).map(function (paramName) {
      var optionObject = {
        data: paramName
      };
      var label = self.getDataForParam(label, paramName);
      if (label) {
        optionObject.label = label + " (|" + paramName + "=)";
      }
      return optionObject;
    });
    if (self.templatedataApiError) {
      // Don't save defaults/guesses to cache;
      return true;
    }
    cache.write(prefixedText + "-params", {
      notemplatedata: self.notemplatedata,
      paramData: self.paramData,
      parameterSuggestions: self.parameterSuggestions,
      paramAliases: self.paramAliases
    }, 1);
    return true;
  }).then(paramDataSet.resolve, paramDataSet.reject);
  return paramDataSet;
};
var makeListAs = function makeListAs(subjectTitle) {
  var name = subjectTitle.getMainText().replace(/\s\(.*\)/, "");
  if (name.indexOf(" ") === -1) {
    return name;
  }
  var generationalSuffix = "";
  if (/ (?:[JS]r.?|[IVX]+)$/.test(name)) {
    generationalSuffix = name.slice(name.lastIndexOf(" "));
    name = name.slice(0, name.lastIndexOf(" "));
    if (name.indexOf(" ") === -1) {
      return name + generationalSuffix;
    }
  }
  var lastName = name.slice(name.lastIndexOf(" ") + 1).replace(/,$/, "");
  var otherNames = name.slice(0, name.lastIndexOf(" "));
  return lastName + ", " + otherNames + generationalSuffix;
};
Template.prototype.addMissingParams = function () {
  var thisTemplate = this;

  // Autofill listas parameter for WP:BIO
  var isBiographyBanner = this.getTitle().getMainText() === "WikiProject Biography" ||
  // TODO: check it
  this.redirectTarget && this.redirectTarget.getMainText() === "WikiProject Biography";
  if (isBiographyBanner && !this.getParam("listas")) {
    var subjectTitle = mw.Title.newFromText(_config["default"].mw.wgPageName).getSubjectPage();
    this.parameters.push({
      name: "listas",
      value: makeListAs(subjectTitle),
      autofilled: true
    });
  }

  // Make sure required/suggested parameters are present
  $.each(thisTemplate.paramData, function (paraName, paraData) {
    if ((paraData.required || paraData.suggested) && !thisTemplate.getParam(paraName)) {
      // Check if already present in an alias, if any
      if (paraData.aliases.length) {
        var aliases = thisTemplate.parameters.filter(function (p) {
          var isAlias = paraData.aliases.includes(p.name);
          var isEmpty = !p.value;
          return isAlias && !isEmpty;
        });
        if (aliases.length) {
          // At least one non-empty alias, so do nothing
          return;
        }
      }
      // No non-empty aliases, so add this to the parameters list (with
      // value set parameter to either the autovaule, or as null).
      // Also set that it was autofilled.
      thisTemplate.parameters.push({
        name: paraName,
        value: paraData.autovalue || null,
        autofilled: true
      });
    }
  });
  return thisTemplate;
};
Template.prototype.setClassesAndImportances = function () {
  var _this = this;
  var parsed = $.Deferred();

  // Don't re-parse if already parsed; no need to parse shell templates or banners without ratings
  if (this.isShellTemplate()) {
    this.classes = _toConsumableArray(_config["default"].bannerDefaults.classes);
    return parsed.resolve();
  } else if (this.classes && this.importances || this.withoutRatings) {
    return parsed.resolve();
  }
  var mainText = this.getTitle().getMainText(); // page name without NS prefix

  // Some projects have hardcoded values, to avoid standard classes or to prevent API issues (timeout and/or node count exceeded)
  var redirectTargetOrMainText = this.redirectTarget ? this.redirectTarget.getMainText() : mainText;
  if (_config["default"].customBanners[redirectTargetOrMainText]) {
    this.classes = _config["default"].customBanners[redirectTargetOrMainText].classes;
    this.importances = _config["default"].customBanners[redirectTargetOrMainText].importances;
    return parsed.resolve();
  }

  // Otherwise try reading from cached data
  var cachedRatings = cache.read(mainText + "-ratings");
  if (cachedRatings && cachedRatings.value && cachedRatings.staleDate && cachedRatings.value.classes != null && cachedRatings.value.importances != null) {
    this.classes = cachedRatings.value.classes;
    this.importances = cachedRatings.value.importances;
    parsed.resolve();
    if (!(0, _util.isAfterDate)(cachedRatings.staleDate)) {
      // Just use the cached data
      return parsed;
    } // else: Use the cache data for now, but also fetch new data from API
  }
  var wikitextToParse = "";
  _config["default"].bannerDefaults.extendedClasses.forEach(function (classname, index) {
    wikitextToParse += "{{" + mainText + "|class=" + classname + "|importance=" + (_config["default"].bannerDefaults.extendedImportances[index] || "") + "}}/n";
  });
  return _api["default"].get({
    action: "parse",
    title: "Talk:沙盒",
    // note: it works even if the page doesn't exist
    text: wikitextToParse,
    prop: "categorieshtml"
  }).then(function /* result */
  () {
    /* var catsHtml = result.parse.categorieshtml["*"];
    var extendedClasses = config.bannerDefaults.extendedClasses.filter(function(cl) {
    	return catsHtml.indexOf(cl+"-Class") !== -1; // i18n
    }); */
    var extendedClasses = _config["default"].bannerDefaults.extendedClasses; // TODO
    _this.classes = [].concat(_toConsumableArray(_config["default"].bannerDefaults.classes), _toConsumableArray(extendedClasses));
    /* this.importances = config.bannerDefaults.extendedImportances.filter(function(imp) {
    	return catsHtml.indexOf(imp+"-importance") !== -1; // i18n
    }); */
    _this.importances = _config["default"].bannerDefaults.extendedImportances; // TODO
    cache.write(mainText + "-ratings", {
      classes: _this.classes,
      importances: _this.importances
    }, 1);
    return true;
  });
};

// </nowiki>

},{"./api":15,"./cache":17,"./config":18,"./util":23}],4:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _config = _interopRequireDefault(require("../../config"));
var _BannerWidget = _interopRequireDefault(require("./BannerWidget"));
var _util = require("../../util");
var _ParameterWidget = _interopRequireDefault(require("./ParameterWidget"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); 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 _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
// <nowiki>

var BannerListWidget = function BannerListWidget(config) {
  config = config || {};

  // Call parent constructor
  BannerListWidget.parent.call(this, config);
  OO.ui.mixin.GroupElement.call(this, {
    $group: this.$element
  });
  this.$element.addClass("rater-bannerListWidget").css({
    "padding": "20px 10px 16px 10px"
  });

  // Prefs
  this.preferences = config.preferences;
  this.oresClass = config.oresClass;
  this.changed = false;

  // Events
  this.aggregate({
    "remove": "bannerRemove"
  });
  this.connect(this, {
    "bannerRemove": "onBannerRemove"
  });
  this.aggregate({
    "changed": "bannerChanged"
  });
  this.connect(this, {
    "bannerChanged": "setChanged"
  });
  this.aggregate({
    "biographyBannerChange": "biographyBannerChanged"
  });
  this.connect(this, {
    "biographyBannerChanged": "syncShellTemplateWithBiographyBanner"
  });
  this.aggregate({
    "updatedSize": "bannerUpdatedSize"
  });
  this.connect(this, {
    "bannerUpdatedSize": "onUpdatedSize"
  });
};
OO.inheritClass(BannerListWidget, OO.ui.Widget);
OO.mixinClass(BannerListWidget, OO.ui.mixin.GroupElement);
/*
methods from mixin:
 - addItems( items, [index] ) : OO.ui.Element  (CHAINABLE)
 - clearItems( ) : OO.ui.Element  (CHAINABLE)
 - findItemFromData( data ) : OO.ui.Element|null
 - findItemsFromData( data ) : OO.ui.Element[]
 - removeItems( items ) : OO.ui.Element  (CHAINABLE)
*/

BannerListWidget.prototype.onUpdatedSize = function () {
  // Emit an "updatedSize" event so the parent window can update size, if needed
  this.emit("updatedSize");
};
BannerListWidget.prototype.setChanged = function () {
  this.changed = true;
};
BannerListWidget.prototype.onBannerRemove = function (banner) {
  this.removeItems([banner]);
  this.setChanged();
};
BannerListWidget.prototype.syncShellTemplateWithBiographyBanner = function (biographyBanner) {
  biographyBanner = biographyBanner || this.items.find(function (banner) {
    return banner.mainText === "WikiProject Biography" || banner.redirectTargetMainText === "WikiProject Biography";
  });
  if (!biographyBanner) return;
  var bannerShellTemplate = this.items.find(function (banner) {
    return banner.mainText === _config["default"].shellTemplates[0] || banner.redirectTargetMainText === _config["default"].shellTemplates[0];
  });
  if (!bannerShellTemplate) {
    return;
  }
  var paramsToSync = [{
    name: "living",
    normalise: true
  }, {
    name: "blpo",
    normalise: true
  }, {
    name: "activepol",
    normalise: true
  }, {
    name: "listas",
    normalise: false
  }];
  paramsToSync.forEach(function (paramToSync) {
    var _map = [biographyBanner, bannerShellTemplate].map(function (banner) {
        return banner.parameterList.getParameterItems().find(function (parameter) {
          return parameter.name === paramToSync.name || banner.paramAliases[parameter.name] === paramToSync.name;
        });
      }),
      _map2 = _slicedToArray(_map, 2),
      biographyParam = _map2[0],
      shellParam = _map2[1];
    if (!biographyParam) return;
    var paramSyncValue = paramToSync.normalise ? (0, _util.normaliseYesNo)(biographyParam.value) : biographyParam.value;
    biographyParam["delete"]();
    if (!shellParam && paramSyncValue) {
      var index = bannerShellTemplate.addParameterLayout.isVisible() ? -1 // Insert at the very end
      : bannerShellTemplate.parameterList.items.length - 1; // Insert prior to the "add parameter" button
      bannerShellTemplate.parameterList.addItems([new _ParameterWidget["default"]({
        "name": paramToSync.name,
        "value": paramSyncValue,
        "autofilled": true
      }, bannerShellTemplate.paramData && bannerShellTemplate.paramData[paramToSync.name])], index);
    } else if (!biographyParam.autofilled && paramSyncValue) {
      shellParam.setValue(paramSyncValue);
      shellParam.setAutofilled();
    }
  });
};
BannerListWidget.prototype.addShellTemplateIfNeeeded = function () {
  var _this = this;
  if (!this.items.some(function (banner) {
    return banner.isShellTemplate;
  })) {
    _BannerWidget["default"].newFromTemplateName(_config["default"].shellTemplates[0], {
      withoutRatings: true
    }, {
      preferences: this.preferences,
      isArticle: this.pageInfo.isArticle
    }).then(function (shellBannerWidget) {
      OO.ui.mixin.GroupElement.prototype.addItems.call(_this, [shellBannerWidget], 0);
      // Autofill ratings (if able to)
      _this.autofillClassRatings({
        forBannerShell: true
      });
      // emit updatedSize event 
      _this.onUpdatedSize();
    });
  }
  return this;
};
BannerListWidget.prototype.addItems = function (items, index) {
  if (items.length === 0) {
    return this;
  }

  // Call mixin method to do the adding
  OO.ui.mixin.GroupElement.prototype.addItems.call(this, items, index);

  // Autofill ratings (if able to, and if enabled in preferences)
  if (!this.items.some(function (banner) {
    return banner.isShellTemplate;
  })) {
    this.autofillClassRatings();
  }
  this.autofillImportanceRatings();

  // emit updatedSize event 
  this.onUpdatedSize();
  return this;
};
BannerListWidget.prototype.autofillClassRatings = function (config) {
  config = config || {};
  // Only autofill if set in preferences
  if (false || !this.preferences.autofillClassFromOthers && !this.preferences.autofillClassFromOres && !config.forBannerShell) {
    return;
  }
  // Check what banners already have
  var uniqueClassRatings = (0, _util.uniqueArray)((0, _util.filterAndMap)(this.items, function (banner) {
    if (banner.isShellTemplate || !banner.hasClassRatings) {
      return false;
    }
    var classItem = banner.classDropdown.getMenu().findSelectedItem();
    return classItem && classItem.getData();
  }, function (banner) {
    return banner.classDropdown.getMenu().findSelectedItem().getData();
  }));
  // Can't autofill if there isn't either a single value, or no value
  if (uniqueClassRatings.length > 1) {
    return;
  }
  // Determine what to autofill with
  var autoClass;
  if (uniqueClassRatings.length === 1 && (this.preferences.autofillClassFromOthers || config.forBannerShell)) {
    autoClass = uniqueClassRatings[0];
  } else if (uniqueClassRatings.length === 0 && this.preferences.autofillClassFromOres && this.oresClass) {
    // Don't autofill above C-class
    switch (this.oresClass) {
      case "Stub":
      case "Start":
      case "C":
      case "List":
        autoClass = this.oresClass;
    }
  } else {
    // nothing to do
    return;
  }
  // Do the autofilling
  this.items.forEach(function (banner) {
    if (!banner.hasClassRatings && !banner.isShellTemplate) {
      return;
    }
    var classItem = banner.classDropdown.getMenu().findSelectedItem();
    if (classItem && classItem.getData() && !config.forBannerShell) {
      return;
    }
    if (config.forBannerShell && !banner.isShellTemplate && classItem.getData() === autoClass) {
      banner.classDropdown.getMenu().selectItemByData(null);
      return;
    }
    banner.classDropdown.getMenu().selectItemByData(autoClass);
    banner.classDropdown.setAutofilled(true);
  });
};
BannerListWidget.prototype.autofillImportanceRatings = function () {
  if (!this.preferences.autofillImportance) {
    return;
  }
  var isRegularArticle = this.pageInfo && this.pageInfo.isArticle && !this.pageInfo.redirect && !this.pageInfo.isDisambig;
  if (!isRegularArticle) {
    return;
  }
  // TODO: Should try to find a smarter, banner-specific way of determining importance.
  // Maybe do something with  ORES's "drafttopic" model.
  var autoImportance = "Low";
  this.items.forEach(function (banner) {
    if (!banner.hasImportanceRatings) {
      return;
    }
    var importanceItem = banner.importanceDropdown.getMenu().findSelectedItem();
    if (importanceItem && importanceItem.getData()) {
      return;
    }
    banner.importanceDropdown.getMenu().selectItemByData(autoImportance);
    banner.importanceDropdown.setAutofilled(true);
  });
};
BannerListWidget.prototype.setPreferences = function (prefs) {
  this.preferences = prefs;
  this.items.forEach(function (banner) {
    return banner.setPreferences(prefs);
  });
  this.autofillClassRatings();
  this.autofillImportanceRatings();
};
BannerListWidget.prototype.makeWikitext = function () {
  var bannersWikitext = (0, _util.filterAndMap)(this.items, function (banner) {
    return !banner.isShellTemplate;
  }, function (banner) {
    return banner.makeWikitext();
  }).join("\n");
  var shellTemplate = this.items.find(function (banner) {
    return banner.isShellTemplate;
  });
  if (!shellTemplate) {
    return bannersWikitext;
  }
  var shellParam1 = new _ParameterWidget["default"]({
    name: "1",
    value: "\n" + bannersWikitext + "\n" + (shellTemplate.nonStandardTemplates ? shellTemplate.nonStandardTemplates + "\n" : "")
  });
  shellTemplate.parameterList.addItems([shellParam1]);
  var shellWikitext = shellTemplate.makeWikitext();
  shellTemplate.parameterList.removeItems([shellParam1]);
  return shellWikitext;
};
var _default = BannerListWidget; // </nowiki>
exports["default"] = _default;

},{"../../config":18,"../../util":23,"./BannerWidget":5,"./ParameterWidget":9}],5:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _config = _interopRequireDefault(require("../../config"));
var _ParameterListWidget = _interopRequireDefault(require("./ParameterListWidget"));
var _ParameterWidget = _interopRequireDefault(require("./ParameterWidget"));
var _DropdownParameterWidget = _interopRequireDefault(require("./DropdownParameterWidget"));
var _SuggestionLookupTextInputWidget = _interopRequireDefault(require("./SuggestionLookupTextInputWidget"));
var _util = require("../../util");
var _Template = require("../../Template");
var _HorizontalLayoutWidget = _interopRequireDefault(require("./HorizontalLayoutWidget"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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; }
// <nowiki>

function BannerWidget(template, config) {
  var _this = this;
  // Configuration initialization
  config = config || {};
  // Call parent constructor
  BannerWidget["super"].call(this, config);
  this.$overlay = config.$overlay;

  /* --- PREFS --- */
  this.preferences = config.preferences;

  /* --- PROPS --- */
  this.paramData = template.paramData;
  this.paramAliases = template.paramAliases || {};
  this.parameterSuggestions = template.parameterSuggestions;
  this.name = template.name;
  this.wikitext = template.wikitext;
  this.pipeStyle = template.pipeStyle;
  this.equalsStyle = template.equalsStyle;
  this.endBracesStyle = template.endBracesStyle;
  this.mainText = template.getTitle().getMainText();
  this.redirectTargetMainText = template.redirectTarget && template.redirectTarget.getMainText();
  this.isShellTemplate = template.isShellTemplate();
  this.changed = template.parameters.some(function (parameter) {
    return parameter.autofilled;
  }); // initially false, unless some parameters were autofilled
  this.hasClassRatings = template.classes && template.classes.length;
  this.hasImportanceRatings = template.importances && template.importances.length;
  this.inactiveProject = template.inactiveProject;

  /* --- TITLE AND RATINGS --- */

  this.getLocalTitleForClasses = function (rName) {
    // TODO: structure
    return _config["default"].bannerDefaultsLabel.extendedClasses.find(function (n) {
      return n.includes(rName + " -");
    }) || _config["default"].bannerDefaultsLabel.classes.find(function (n) {
      return n.includes(rName + " -");
    }) || rName;
  };
  this.getLocalTitleForImportances = function (rName) {
    return _config["default"].bannerDefaultsLabel.importances.find(function (n) {
      return n.includes(rName + " -");
    }) || _config["default"].bannerDefaultsLabel.extendedImportances.find(function (n) {
      return n.includes(rName + " -");
    }) || rName;
  };
  this.openButton = new OO.ui.ButtonWidget({
    icon: "link",
    label: wgULS("打开页面", "打开页面"),
    title: wgULS("打开页面", "打开页面"),
    $element: $("<div style=\"width:100%\">")
  });
  this.removeButton = new OO.ui.ButtonWidget({
    icon: "trash",
    label: wgULS("移除横幅", "移除橫幅"),
    title: wgULS("移除横幅", "移除橫幅"),
    flags: "destructive",
    $element: $("<div style=\"width:100%\">")
  });
  this.clearButton = new OO.ui.ButtonWidget({
    icon: "cancel",
    label: wgULS("清空参数", "清除參數"),
    title: wgULS("清空参数", "清除參數"),
    flags: "destructive",
    $element: $("<div style=\"width:100%\">")
  });
  this.openButton.$element.find("a").css("width", "100%");
  this.removeButton.$element.find("a").css("width", "100%");
  this.clearButton.$element.find("a").css("width", "100%");
  this.titleButtonsGroup = new OO.ui.ButtonGroupWidget({
    items: [this.removeButton, this.clearButton, this.openButton],
    $element: $("<span style='width:100%;'>")
  });
  this.mainLabelPopupButton = new OO.ui.PopupButtonWidget({
    label: "{{".concat(template.getTitle().getMainText(), "}}").concat(this.inactiveProject ? wgULS("(不活跃)", "(不活躍)") : ""),
    $element: $("<span style='display:inline-block;width:48%;margin-right:0;padding-right:8px'>"),
    $overlay: this.$overlay,
    indicator: "down",
    framed: false,
    popup: {
      $content: this.titleButtonsGroup.$element,
      width: 200,
      padded: false,
      align: "force-right",
      anchor: false
    }
  });
  this.mainLabelPopupButton.$element.children("a").first().css({
    "font-size": "110%"
  }).find("span.oo-ui-labelElement-label").css({
    "white-space": "normal"
  });

  // Rating dropdowns
  if (this.isShellTemplate) {
    this.classDropdown = new _DropdownParameterWidget["default"]({
      label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">Class</span>"),
      menu: {
        items: [new OO.ui.MenuOptionWidget({
          data: null,
          label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">\uFF08".concat(config.isArticle ? wgULS("无质量", "未評定") : wgULS("自动检测", "自動偵測"), "\uFF09</span>"))
        })].concat(_toConsumableArray(_config["default"].bannerDefaults.classes.map(function (classname) {
          return new OO.ui.MenuOptionWidget({
            data: classname,
            label: _this.getLocalTitleForClasses(classname)
          });
        })))
      },
      $overlay: this.$overlay
    });
    var shellClassParam = template.parameters.find(function (parameter) {
      return parameter.name === "class";
    });
    this.classDropdown.getMenu().selectItemByData(shellClassParam && (0, _util.classMask)(shellClassParam.value));
  } else if (this.hasClassRatings) {
    this.classDropdown = new _DropdownParameterWidget["default"]({
      label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">" + "质量" + "</span>"),
      menu: {
        items: [new OO.ui.MenuOptionWidget({
          data: null,
          label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">".concat(config.isArticle ? wgULS("(继承自shell)", "(繼承自shell)") : wgULS("(自动检测)", "(自動偵測)"), "</span>"))
        })].concat(_toConsumableArray(template.classes.map(function (classname) {
          return new OO.ui.MenuOptionWidget({
            data: classname,
            label: _this.getLocalTitleForClasses(classname)
          });
        })))
      },
      $overlay: this.$overlay
    });
    var classParam = template.parameters.find(function (parameter) {
      return parameter.name === "class";
    });
    this.classDropdown.getMenu().selectItemByData(classParam && (0, _util.classMask)(classParam.value));
  }
  if (this.hasImportanceRatings) {
    this.importanceDropdown = new _DropdownParameterWidget["default"]({
      label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">重要度</span>"),
      menu: {
        items: [new OO.ui.MenuOptionWidget({
          data: null,
          label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">".concat(config.isArticle ? wgULS("(无重要度)", "(未評定)") : wgULS("(自动检测)", "(自動偵測)"), "</span>"))
        })].concat(_toConsumableArray(template.importances.map(function (importance) {
          return new OO.ui.MenuOptionWidget({
            data: importance,
            label: _this.getLocalTitleForImportances(importance)
          });
        })))
      },
      $overlay: this.$overlay
    });
    var importanceParam = template.parameters.find(function (parameter) {
      return parameter.name === "importance";
    });
    this.importanceDropdown.getMenu().selectItemByData(importanceParam && (0, _util.importanceMask)(importanceParam.value));
  }
  this.titleLayout = new OO.ui.HorizontalLayout({
    items: [this.mainLabelPopupButton]
  });
  if (this.hasClassRatings || this.isShellTemplate) {
    this.titleLayout.addItems([this.classDropdown]);
  }
  if (this.hasImportanceRatings) {
    this.titleLayout.addItems([this.importanceDropdown]);
  }

  /* --- PARAMETERS LIST --- */

  var parameterWidgets = (0, _util.filterAndMap)(template.parameters, function (param) {
    if (_this.isShellTemplate) {
      if (param.name == "1") {
        _this.shellParam1Value = param.value;
        return false;
      }
      return param.name !== "class";
    }
    return param.name !== "class" && param.name !== "importance";
  }, function (param) {
    return new _ParameterWidget["default"](param, template.paramData[param.name], {
      $overlay: _this.$overlay
    });
  });
  this.parameterList = new _ParameterListWidget["default"]({
    items: parameterWidgets,
    preferences: this.preferences
  });

  /* --- ADD PARAMETER SECTION --- */

  this.addParameterNameInput = new _SuggestionLookupTextInputWidget["default"]({
    suggestions: template.parameterSuggestions,
    placeholder: wgULS("参数名", "參數名稱"),
    $element: $("<div style='display:inline-block;width:40%'>"),
    validate: function (val) {
      var _this$getAddParameter = this.getAddParametersInfo(val),
        validName = _this$getAddParameter.validName,
        name = _this$getAddParameter.name,
        value = _this$getAddParameter.value;
      return !name && !value ? true : validName;
    }.bind(this),
    allowSuggestionsWhenEmpty: true,
    $overlay: this.$overlay
  });
  this.updateAddParameterNameSuggestions();
  this.addParameterValueInput = new _SuggestionLookupTextInputWidget["default"]({
    placeholder: wgULS("参数值", "參數內容"),
    $element: $("<div style='display:inline-block;width:40%'>"),
    validate: function (val) {
      var _this$getAddParameter2 = this.getAddParametersInfo(null, val),
        validValue = _this$getAddParameter2.validValue,
        name = _this$getAddParameter2.name,
        value = _this$getAddParameter2.value;
      return !name && !value ? true : validValue;
    }.bind(this),
    allowSuggestionsWhenEmpty: true,
    $overlay: this.$overlay
  });
  this.addParameterButton = new OO.ui.ButtonWidget({
    label: wgULS("添加", "新增"),
    icon: "add",
    flags: "progressive"
  }).setDisabled(true);
  this.addParameterControls = new _HorizontalLayoutWidget["default"]({
    items: [this.addParameterNameInput, new OO.ui.LabelWidget({
      label: "="
    }), this.addParameterValueInput, this.addParameterButton]
  });
  this.addParameterLayout = new OO.ui.FieldLayout(this.addParameterControls, {
    label: wgULS("添加参数:", "新增參數:"),
    align: "top"
  }).toggle(false);
  // A hack to make messages appear on their own line
  this.addParameterLayout.$element.find(".oo-ui-fieldLayout-messages").css({
    "clear": "both",
    "padding-top": 0
  });

  /* --- OVERALL LAYOUT/DISPLAY --- */

  // Display the layout elements, and a rule
  this.$element.addClass("rater-bannerWidget").append(this.titleLayout.$element, this.parameterList.$element, this.addParameterLayout.$element);
  if (!this.isShellTemplate) {
    this.$element.append($("<hr>"));
  }
  if (this.isShellTemplate) {
    this.$element.css({
      "background": "#eee",
      "border-radius": "10px",
      "padding": "0 10px 5px",
      "margin-bottom": "12px",
      "font-size": "92%"
    });
  }

  /* --- EVENT HANDLING --- */

  if (this.hasClassRatings) {
    this.classDropdown.connect(this, {
      "change": "onClassChange"
    });
  }
  if (this.hasImportanceRatings) {
    this.importanceDropdown.connect(this, {
      "change": "onImportanceChange"
    });
  }
  this.parameterList.connect(this, {
    "change": "onParameterChange",
    "addParametersButtonClick": "showAddParameterInputs",
    "updatedSize": "onUpdatedSize"
  });
  this.addParameterButton.connect(this, {
    "click": "onParameterAdd"
  });
  this.addParameterNameInput.connect(this, {
    "change": "onAddParameterNameChange",
    "enter": "onAddParameterNameEnter",
    "choose": "onAddParameterNameEnter"
  });
  this.addParameterValueInput.connect(this, {
    "change": "onAddParameterValueChange",
    "enter": "onAddParameterValueEnter",
    "choose": "onAddParameterValueEnter"
  });
  this.openButton.connect(this, {
    "click": "onOpenButtonClick"
  });
  this.removeButton.connect(this, {
    "click": "onRemoveButtonClick"
  });
  this.clearButton.connect(this, {
    "click": "onClearButtonClick"
  });

  /* --- APPLY PREF -- */
  if (this.preferences.bypassRedirects) {
    this.bypassRedirect();
  }
}
OO.inheritClass(BannerWidget, OO.ui.Widget);

/**
 * @param {String} templateName
 * @param {Object} [data]
 * @param {Boolean} data.withoutRatings
 * @param {Boolean} data.isWrapper
 * @param {Object} config
 * @returns {Promise<BannerWidget>}
 */
BannerWidget.newFromTemplateName = function (templateName, data, config) {
  var template = new _Template.Template();
  template.name = templateName;
  if (data && data.withoutRatings) {
    template.withoutRatings = true;
  }
  return (0, _Template.getWithRedirectTo)(template).then(function (template) {
    return $.when(template.setClassesAndImportances(), template.setParamDataAndSuggestions()).then(function () {
      // Add missing required/suggested values
      template.addMissingParams();
      // Return the now-modified template
      return template;
    });
  }).then(function (template) {
    return new BannerWidget(template, config);
  });
};
BannerWidget.prototype.onUpdatedSize = function () {
  // Emit an "updatedSize" event so the parent window can update size, if needed
  this.emit("updatedSize");
};
BannerWidget.prototype.setChanged = function () {
  this.changed = true;
  this.emit("changed");
  // TODO: check it
  if (this.mainText === "WikiProject Biography" || this.redirectTargetMainText === "WikiProject Biography") {
    // Emit event so BannerListWidget can update the banner shell template (if present)
    this.emit("biographyBannerChange");
  }
};
BannerWidget.prototype.onParameterChange = function () {
  this.setChanged();
  this.updateAddParameterNameSuggestions();
};
BannerWidget.prototype.onClassChange = function () {
  this.setChanged();
  this.classChanged = true;
  var classItem = this.classDropdown.getMenu().findSelectedItem();
  if (classItem && classItem.getData() == null) {
    // clear selection
    this.classDropdown.getMenu().selectItem();
  }
};
BannerWidget.prototype.onImportanceChange = function () {
  this.setChanged();
  this.importanceChanged = true;
  var importanceItem = this.importanceDropdown.getMenu().findSelectedItem();
  if (importanceItem && importanceItem.getData() == null) {
    // clear selection
    this.importanceDropdown.getMenu().selectItem();
  }
};
BannerWidget.prototype.showAddParameterInputs = function () {
  this.addParameterLayout.toggle(true);
  this.addParameterNameInput.focus();
  this.onUpdatedSize();
};
BannerWidget.prototype.getAddParametersInfo = function (nameInputVal, valueInputVal) {
  var name = nameInputVal && nameInputVal.trim() || this.addParameterNameInput.getValue().trim();
  var paramAlreadyIncluded = name === "class" || name === "importance" || name === "1" && this.isShellTemplate || this.parameterList.getParameterItems().some(function (paramWidget) {
    return paramWidget.name === name;
  });
  var value = valueInputVal && valueInputVal.trim() || this.addParameterValueInput.getValue().trim();
  var autovalue = name && this.paramData[name] && this.paramData[name].autovalue || null;
  return {
    validName: !!(name && !paramAlreadyIncluded),
    validValue: !!(value || autovalue),
    isAutovalue: !!(!value && autovalue),
    isAlreadyIncluded: !!(name && paramAlreadyIncluded),
    name: name,
    value: value,
    autovalue: autovalue
  };
};
BannerWidget.prototype.onAddParameterNameChange = function () {
  var _this$getAddParameter3 = this.getAddParametersInfo(),
    validName = _this$getAddParameter3.validName,
    validValue = _this$getAddParameter3.validValue,
    isAutovalue = _this$getAddParameter3.isAutovalue,
    isAlreadyIncluded = _this$getAddParameter3.isAlreadyIncluded,
    name = _this$getAddParameter3.name,
    autovalue = _this$getAddParameter3.autovalue; // Set value input placeholder as the autovalue
  this.addParameterValueInput.$input.attr("placeholder", autovalue || "");
  // Set suggestions, if the parameter has a list of allowed values
  var allowedValues = this.paramData[name] && this.paramData[name].allowedValues && this.paramData[name].allowedValues.map(function (val) {
    return {
      data: val,
      label: val
    };
  });
  this.addParameterValueInput.setSuggestions(allowedValues || []);
  // Set button disabled state based on validity
  this.addParameterButton.setDisabled(!validName || !validValue);
  // Show notice if autovalue will be used
  this.addParameterLayout.setNotices(validName && isAutovalue ? [wgULS("将自动填写参数值", "將自動填寫參數值")] : []);
  // Show error is the banner already has the parameter set
  this.addParameterLayout.setErrors(isAlreadyIncluded ? [wgULS("参数已存在", "參數已存在")] : []);
};
BannerWidget.prototype.onAddParameterNameEnter = function () {
  this.addParameterValueInput.focus();
};
BannerWidget.prototype.onAddParameterValueChange = function () {
  var _this$getAddParameter4 = this.getAddParametersInfo(),
    validName = _this$getAddParameter4.validName,
    validValue = _this$getAddParameter4.validValue,
    isAutovalue = _this$getAddParameter4.isAutovalue;
  this.addParameterButton.setDisabled(!validName || !validValue);
  this.addParameterLayout.setNotices(validName && isAutovalue ? ["将自动填写参数值"] : []);
};
BannerWidget.prototype.onAddParameterValueEnter = function () {
  // Make sure button state has been updated
  this.onAddParameterValueChange();
  // Do nothing if button is disabled (i.e. name and/or value are invalid)
  if (this.addParameterButton.isDisabled()) {
    return;
  }
  // Add parameter
  this.onParameterAdd();
};
BannerWidget.prototype.onParameterAdd = function () {
  var _this$getAddParameter5 = this.getAddParametersInfo(),
    validName = _this$getAddParameter5.validName,
    validValue = _this$getAddParameter5.validValue,
    name = _this$getAddParameter5.name,
    value = _this$getAddParameter5.value,
    autovalue = _this$getAddParameter5.autovalue;
  if (!validName || !validValue) {
    // Error should already be shown via onAddParameter...Change methods
    return;
  }
  var newParameter = new _ParameterWidget["default"]({
    "name": name,
    "value": value || autovalue
  }, this.paramData[name], {
    $overlay: this.$overlay
  });
  this.parameterList.addItems([newParameter]);
  this.addParameterNameInput.setValue("");
  this.addParameterValueInput.setValue("");
  this.addParameterNameInput.$input.focus();
};
BannerWidget.prototype.updateAddParameterNameSuggestions = function () {
  var paramsInUse = {};
  this.parameterList.getParameterItems().forEach(function (paramWidget) {
    return paramsInUse[paramWidget.name] = true;
  });
  this.addParameterNameInput.setSuggestions(this.parameterSuggestions.filter(function (suggestion) {
    return !paramsInUse[suggestion.data];
  }));
};
BannerWidget.prototype.onOpenButtonClick = function () {
  window.open(mw.util.getUrl("Template:" + this.name), '_blank');
};
BannerWidget.prototype.onRemoveButtonClick = function () {
  this.emit("remove");
};
BannerWidget.prototype.onClearButtonClick = function () {
  this.parameterList.clearItems(this.parameterList.getParameterItems());
  if (this.hasClassRatings) {
    this.classDropdown.getMenu().selectItem();
  }
  if (this.hasImportanceRatings) {
    this.importanceDropdown.getMenu().selectItem();
  }
};
BannerWidget.prototype.bypassRedirect = function () {
  if (!this.redirectTargetMainText) {
    return;
  }
  // Store the bypassed name
  this.bypassedName = this.name;
  // Update title label
  this.mainLabelPopupButton.setLabel("{{".concat(this.redirectTargetMainText, "}}").concat(this.inactiveProject ? wgULS("(不活跃)", "(不活躍)") : ""));
  // Update properties
  this.name = this.redirectTargetMainText;
  this.mainText = this.redirectTargetMainText;
  this.redirectTargetMainText = null;
  this.setChanged();
};
BannerWidget.prototype.makeWikitext = function () {
  if (!this.changed && this.wikitext) {
    return this.wikitext;
  }
  var pipe = this.pipeStyle;
  var equals = this.equalsStyle;
  var classItem = (this.hasClassRatings || this.isShellTemplate) && this.classDropdown.getMenu().findSelectedItem();
  var classVal = classItem && classItem.getData();
  var importanceItem = this.hasImportanceRatings && this.importanceDropdown.getMenu().findSelectedItem();
  var importanceVal = importanceItem && importanceItem.getData();
  return ("{{" + this.name + ((this.hasClassRatings || this.isShellTemplate) && classVal != null ? "".concat(pipe, "class").concat(equals).concat(classVal || "") : "") + (this.hasImportanceRatings && importanceVal != null ? "".concat(pipe, "importance").concat(equals).concat(importanceVal || "") : "") + this.parameterList.getParameterItems().map(function (parameter) {
    return parameter.makeWikitext(pipe, equals);
  }).join("") + this.endBracesStyle).replace(/\n+}}$/, "\n}}"); // avoid empty line at end like [[Special:Diff/925982142]]
};
BannerWidget.prototype.setPreferences = function (prefs) {
  this.preferences = prefs;
  if (this.preferences.bypassRedirects) {
    this.bypassRedirect();
  }
  this.parameterList.setPreferences(prefs);
};
var _default = BannerWidget; // </nowiki>
exports["default"] = _default;

},{"../../Template":3,"../../config":18,"../../util":23,"./DropdownParameterWidget":6,"./HorizontalLayoutWidget":7,"./ParameterListWidget":8,"./ParameterWidget":9,"./SuggestionLookupTextInputWidget":11}],6:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
// <nowiki>

function DropdownParameterWidget(config) {
  // Configuration initialization
  config = $.extend({
    $element: $("<span style='display:inline-block;width:24%'>")
  }, config || {});

  // Call parent constructor
  DropdownParameterWidget["super"].call(this, config);
  this.$overlay = config.$overlay;
  this.$element.addClass("rater-dropdownParameterWidget");

  // Autofilled icon
  this.autofilled = !!config.autofilled;
  this.autofilledIcon = new OO.ui.IconWidget({
    icon: "robot",
    title: "自動填寫",
    flags: "progressive",
    $element: $("<span style='margin: 0 -5px 0 5px;min-width: 16px;width: 16px;left:unset;'>")
  }).toggle(this.autofilled);
  this.$element.find(".oo-ui-indicatorElement-indicator").before(this.autofilledIcon.$element);

  // Events
  this.menu.connect(this, {
    "choose": "onDropdownMenuChoose",
    "select": "onDropdownMenuSelect"
  });
}
OO.inheritClass(DropdownParameterWidget, OO.ui.DropdownWidget);
DropdownParameterWidget.prototype.setAutofilled = function (setAutofill) {
  this.autofilledIcon.toggle(!!setAutofill);
  this.$element.find(".oo-ui-dropdownWidget-handle").css({
    "border": setAutofill ? "1px dashed #36c" : ""
  });
  this.autofilled = !!setAutofill;
};
DropdownParameterWidget.prototype.onDropdownMenuChoose = function () {
  this.setAutofilled(false);
  this.emit("change");
};
DropdownParameterWidget.prototype.onDropdownMenuSelect = function () {
  this.emit("change");
};
DropdownParameterWidget.prototype.getValue = function () {
  var selectedItem = this.menu.findSelectedItem();
  return selectedItem && selectedItem.getData();
};
var _default = DropdownParameterWidget; // </nowiki>
exports["default"] = _default;

},{}],7:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
// <nowiki>

/**
 * A HorizontalLayout that is also a widget, and can thus be placed within
 * field layouts.
 * 
 * @class
 * @param {*} config configuration for OO.ui.HorizontalLayout
 */
function HorizontalLayoutWidget(config) {
  // Configuration initialization
  config = config || {};
  // Call parent constructor
  HorizontalLayoutWidget["super"].call(this, {});
  this.layout = new OO.ui.HorizontalLayout(_objectSpread({}, config, {
    $element: this.$element
  }));
}
OO.inheritClass(HorizontalLayoutWidget, OO.ui.Widget);
var _default = HorizontalLayoutWidget; // </nowiki>
exports["default"] = _default;

},{}],8:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
// <nowiki>

/**
 * @cfg {OO.ui.Element[]} items Items to be added
 * @cfg {Number} displayLimit The most to show at once. If the number of items
 *  is more than this, then only the first (displayLimit - 1) items are shown.
 */
var ParameterListWidget = function ParameterListWidget(config) {
  config = config || {};

  // Call parent constructor
  ParameterListWidget.parent.call(this, config);
  OO.ui.mixin.GroupElement.call(this, {
    $group: this.$element
  });
  this.addItems(config.items);
  this.$element.addClass("rater-parameterListWidget");
  this.preferences = config.preferences;

  // Hide some parameters (initially), if more than set display limit -- which is the 
  // one more than collapseParamsLowerLimit, to prevent only one param being hidden
  // (mostly: may occasionally occur if params were auto-filled).
  var displayLimit = this.preferences.collapseParamsLowerLimit + 1;
  if (displayLimit && this.items.length > displayLimit) {
    var hideFromNumber = displayLimit - 1; // One-indexed
    var hideFromIndex = hideFromNumber - 1; // Zero-indexed
    var hiddenCount = 0;
    for (var i = hideFromIndex; i < this.items.length; i++) {
      if (!this.items[i].autofilled) {
        // Don't hide auto-filled params
        this.items[i].toggle(false);
        hiddenCount++;
      }
    }
    if (hiddenCount > 0) {
      // Add button to show the hidden params
      this.showMoreParametersButton = new OO.ui.ButtonWidget({
        label: wgULS("显示额外", "顯示其他") + hiddenCount + wgULS("个参数", "個參數"),
        framed: false,
        $element: $("<span style='margin-bottom:0'>")
      });
      this.addItems([this.showMoreParametersButton]);
    }
  }

  // Add the button that allows user to add more parameters
  this.addParametersButton = new OO.ui.ButtonWidget({
    label: wgULS("添加参数", "新增參數"),
    icon: "add",
    framed: false,
    $element: $("<span style='margin-bottom:0'>")
  });
  this.addItems([this.addParametersButton]);

  /* --- Events --- */

  // Handle delete events from ParameterWidgets
  this.aggregate({
    "delete": "parameterDelete"
  });
  this.connect(this, {
    parameterDelete: "onParameterDelete"
  });

  // Handle change events from ParameterWidgets
  this.aggregate({
    change: "parameterChange"
  });
  this.connect(this, {
    parameterChange: "onParameterChange"
  });

  // Handle updatedSize events from ParameterWidgets
  this.aggregate({
    "updatedSize": "parameterUpdatedSize"
  });
  this.connect(this, {
    "parameterUpdatedSize": "onUpdatedSize"
  });

  // Handle button clicks
  if (this.showMoreParametersButton) {
    this.showMoreParametersButton.connect(this, {
      "click": "onShowMoreParametersButtonClick"
    });
  }
  this.addParametersButton.connect(this, {
    "click": "onAddParametersButtonClick"
  });
};
OO.inheritClass(ParameterListWidget, OO.ui.Widget);
OO.mixinClass(ParameterListWidget, OO.ui.mixin.GroupElement);
/*
methods from mixin:
 - addItems( items, [index] ) : OO.ui.Element  (CHAINABLE)
 - clearItems( ) : OO.ui.Element  (CHAINABLE)
 - findItemFromData( data ) : OO.ui.Element|null
 - findItemsFromData( data ) : OO.ui.Element[]
 - removeItems( items ) : OO.ui.Element  (CHAINABLE)
*/

ParameterListWidget.prototype.onUpdatedSize = function () {
  // Emit an "updatedSize" event so the parent window can update size, if needed
  this.emit("updatedSize");
};
ParameterListWidget.prototype.addItems = function (items, index) {
  if (items.length === 0) {
    return this;
  }

  // Call mixin method to do the adding
  OO.ui.mixin.GroupElement.prototype.addItems.call(this, items, index);

  // emit updatedSize event 
  this.onUpdatedSize();
  return this;
};
ParameterListWidget.prototype.onParameterDelete = function (parameter) {
  this.removeItems([parameter]);
  this.emit("change");
};
ParameterListWidget.prototype.onParameterChange = function () {
  this.emit("change");
};
ParameterListWidget.prototype.getParameterItems = function () {
  return this.items.filter(function (item) {
    return item.constructor.name === "ParameterWidget";
  });
};
ParameterListWidget.prototype.onShowMoreParametersButtonClick = function () {
  this.removeItems([this.showMoreParametersButton]);
  this.items.forEach(function (parameterWidget) {
    return parameterWidget.toggle(true);
  });
  this.onUpdatedSize();
};
ParameterListWidget.prototype.onAddParametersButtonClick = function () {
  this.removeItems([this.addParametersButton]);
  this.emit("addParametersButtonClick");
};
ParameterListWidget.prototype.makeWikitext = function (pipeStyle, equalsStyle) {
  return this.getParameterItems().map(function (parameter) {
    return parameter.makeWikitext(pipeStyle, equalsStyle);
  }).join("");
};
ParameterListWidget.prototype.setPreferences = function (prefs) {
  this.preferences = prefs;
  var params = this.getParameterItems();
  // Unhide some parameters of the collapseParamsLowerLimit has increased.
  // (Not hiding any if it decreased, since it's a *lower* limit of what needs to be shown.)
  if (params.length <= this.preferences.collapseParamsLowerLimit) {
    return;
  }
  var hiddenParams = params.filter(function (param) {
    return !param.isVisible();
  });
  var visibleParamsCount = params.length - hiddenParams.length;
  if (hiddenParams === 0 || visibleParamsCount >= this.preferences.collapseParamsLowerLimit) {
    return;
  }
  var numToUnhide = Math.min(this.preferences.collapseParamsLowerLimit - visibleParamsCount, hiddenParams.length);
  for (var i = 0; i < numToUnhide; i++) {
    hiddenParams[i].toggle(true);
  }
  var stillHiddenCount = hiddenParams.length - numToUnhide;
  if (stillHiddenCount === 0) {
    this.removeItems([this.showMoreParametersButton]);
  } else {
    this.showMoreParametersButton.setLabel(wgULS("显示额外", "顯示其他") + stillHiddenCount + wgULS("个参数", "個參數"));
  }
};
var _default = ParameterListWidget; // </nowiki>
exports["default"] = _default;

},{}],9:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _util = require("../../util");
var _HorizontalLayoutWidget = _interopRequireDefault(require("./HorizontalLayoutWidget"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

function ParameterWidget(parameter, paramData, config) {
  // Configuration initialization
  config = config || {};
  // Call parent constructor
  ParameterWidget["super"].call(this, config);
  this.$overlay = config.$overlay;
  this.name = parameter.name;
  this.value = parameter.value;
  this.autofilled = parameter.autofilled;
  this.isInvalid = parameter.value == null;
  this.paramData = paramData || {};
  this.allowedValues = this.paramData.allowedValues || [];
  this.isRequired = this.paramData.required;
  this.isSuggested = this.paramData.suggested;

  // Make a checkbox if only 1 or 2 allowed values
  switch (this.allowedValues.length) {
    /* eslint-disable no-fallthrough */
    case 1:
      this.allowedValues[1] = null;
    /* fall-through */
    case 2:
      var isFirstAllowedVal = this.allowedValues.indexOf(parameter.value) === 0 || this.allowedValues.map(_util.normaliseYesNo).indexOf((0, _util.normaliseYesNo)(parameter.value)) === 0;
      var isSecondAllowedVal = this.allowedValues.indexOf(parameter.value || null) === 1 || this.allowedValues.map(_util.normaliseYesNo).indexOf(parameter.value ? (0, _util.normaliseYesNo)(parameter.value) : null) === 1;
      var isIndeterminate = !isFirstAllowedVal && !isSecondAllowedVal;
      this.checkbox = new OO.ui.CheckboxInputWidget({
        selected: isIndeterminate ? undefined : isFirstAllowedVal,
        indeterminate: isIndeterminate ? true : undefined,
        $element: $("<label style='margin:0 0 0 5px'>")
      });
      break;
    default:
    // No checkbox
  } /* eslint-enable no-fallthrough */

  /* --- EDIT PARAMETER LAYOUT --- */

  this.input = new OO.ui.ComboBoxInputWidget({
    value: this.value,
    // label: parameter.name + " =",
    // labelPosition: "before",
    options: (0, _util.filterAndMap)(this.allowedValues, function (val) {
      return val !== null;
    }, function (val) {
      return {
        data: val,
        label: val
      };
    }),
    $element: $("<div style='margin-bottom:0;'>"),
    $overlay: this.$overlay
  });
  // Reduce the excessive whitespace/height
  this.input.$element.find("input").css({
    "padding-top": 0,
    "padding-bottom": "2px",
    "height": "24px"
  });
  // Fix label positioning within the reduced height
  this.input.$element.find("span.oo-ui-labelElement-label").css({
    "line-height": "normal"
  });
  // Also reduce height of dropdown button (if options are present)
  this.input.$element.find("a.oo-ui-buttonElement-button").css({
    "padding-top": 0,
    "height": "24px",
    "min-height": "0"
  });
  this.confirmButton = new OO.ui.ButtonWidget({
    icon: "check",
    label: "完成",
    framed: false,
    flags: "progressive",
    $element: $("<span style='margin-right:0'>")
  });
  this.cancelButton = new OO.ui.ButtonWidget({
    icon: "undo",
    label: "取消",
    framed: false
  });
  this.deleteButton = new OO.ui.ButtonWidget({
    icon: this.isRequired ? "restore" : "trash",
    label: this.isRequired ? wgULS("必填参数", "必要參數") : wgULS("删除", "刪除"),
    framed: false,
    flags: "destructive",
    disabled: this.isRequired
  });
  this.editButtonControls = new OO.ui.ButtonGroupWidget({
    items: [this.confirmButton, this.cancelButton, this.deleteButton],
    $element: $("<span style='font-size:92%'>")
  });
  this.editButtonControls.$element.find("a span:first-child").css({
    "min-width": "unset",
    "width": "16px",
    "margin-right": 0
  });
  this.editLayoutControls = new _HorizontalLayoutWidget["default"]({
    items: [this.input, this.editButtonControls]
    //$element: $("<div style='width: 48%;margin:0;'>")
  });
  this.editLayout = new OO.ui.FieldLayout(this.editLayoutControls, {
    label: this.name + " =",
    align: "top",
    help: this.paramData.description && this.paramData.description.zh || false,
    helpInline: true
  }).toggle();
  this.editLayout.$element.find("label.oo-ui-inline-help").css({
    "margin": "-10px 0 5px 10px"
  });

  /* --- READ (COLLAPSED) DISPLAY OF PARAMETER --- */

  this.invalidIcon = new OO.ui.IconWidget({
    icon: "block",
    title: "无效参数:没有指定值!",
    flags: "destructive",
    $element: $("<span style='margin: 0 5px 0 -5px; min-width: 16px; width: 16px;'>")
  }).toggle(this.isInvalid);
  this.fullLabel = new OO.ui.LabelWidget({
    label: this.name + (this.value ? " = " + this.value : " "),
    $element: $("<label style='margin: 0;'>")
  });
  this.autofilledIcon = new OO.ui.IconWidget({
    icon: "robot",
    title: "自动填写",
    flags: "progressive",
    $element: $("<span style='margin: 0 -5px 0 5px;min-width: 16px;width: 16px;'>")
  }).toggle(this.autofilled);
  this.editButton = new OO.ui.ButtonWidget({
    icon: "edit",
    framed: false,
    $element: $("<span style='margin-bottom: 0;'>")
  });
  this.editButton.$element.find("a").css({
    "border-radius": "0 10px 10px 0",
    "margin-left": "5px"
  });
  this.editButton.$element.find("a span").first().css({
    "min-width": "unset",
    "width": "16px"
  });
  this.readLayout = new OO.ui.HorizontalLayout({
    items: [this.invalidIcon, this.fullLabel, this.autofilledIcon, this.editButton],
    $element: $("<span style='margin:0;width:unset;'>")
  });
  if (this.checkbox) {
    this.readLayout.addItems([this.checkbox], 2);
  }

  /* --- CONTAINER FOR BOTH LAYOUTS --- */
  this.$element = $("<div>").addClass("rater-parameterWidget").css({
    "width": "unset",
    "display": "inline-block",
    "border": this.autofilled ? "1px dashed #36c" : "1px solid #ddd",
    "border-radius": "10px",
    "padding-left": "10px",
    "margin": "0 8px 8px 0",
    "background": this.isInvalid ? "#fddd" : "#fffe"
  }).append(this.readLayout.$element, this.editLayout.$element);
  this.editButton.connect(this, {
    "click": "onEditClick"
  });
  this.confirmButton.connect(this, {
    "click": "onConfirmClick"
  });
  this.cancelButton.connect(this, {
    "click": "onCancelClick"
  });
  this.deleteButton.connect(this, {
    "click": "onDeleteClick"
  });
  if (this.checkbox) {
    this.checkbox.connect(this, {
      "change": "onCheckboxChange"
    });
  }
}
OO.inheritClass(ParameterWidget, OO.ui.Widget);
ParameterWidget.prototype.onUpdatedSize = function () {
  // Emit an "updatedSize" event so the parent window can update size, if needed
  this.emit("updatedSize");
};
ParameterWidget.prototype.onEditClick = function () {
  this.readLayout.toggle(false);
  this.editLayout.toggle(true);
  this.$element.css({
    "background": "#fffe"
  });
  this.input.focus();
  this.onUpdatedSize();
};
ParameterWidget.prototype.onConfirmClick = function () {
  this.setValue(this.input.getValue());
  this.readLayout.toggle(true);
  this.editLayout.toggle(false);
  this.onUpdatedSize();
};
ParameterWidget.prototype.onCancelClick = function () {
  this.input.setValue(this.value);
  this.readLayout.toggle(true);
  this.editLayout.toggle(false);
  this.onUpdatedSize();
};
ParameterWidget.prototype.onDeleteClick = function () {
  this["delete"]();
};
ParameterWidget.prototype.onCheckboxChange = function (isSelected, isIndeterminate) {
  if (isIndeterminate) {
    return;
  }
  if (isSelected) {
    this.setValue(this.allowedValues[0]);
  } else {
    this.setValue(this.allowedValues[1]);
  }
};
ParameterWidget.prototype["delete"] = function () {
  this.emit("delete");
};
ParameterWidget.prototype.setValue = function (val) {
  // Turn off autofill stylings/icon
  this.autofilled = false;
  this.autofilledIcon.toggle(false);
  this.$element.css({
    "border": "1px solid #ddd"
  });

  // Update the stored value
  this.value = val;

  // Update the input value for edit mode
  this.input.setValue(this.value);

  // Update validity
  this.isInvalid = this.value == null;
  this.invalidIcon.toggle(this.isInvalid);
  this.$element.css({
    "background": this.isInvalid ? "#fddd" : "#fffe"
  });

  // Updated the label for read mode
  this.fullLabel.setLabel(this.name + (this.value ? " = " + this.value : ""));

  // Update the checkbox (if there is one)
  if (this.checkbox) {
    var isFirstAllowedVal = this.allowedValues.indexOf(val) === 0 || this.allowedValues.map(_util.normaliseYesNo).indexOf((0, _util.normaliseYesNo)(val)) === 0;
    var isSecondAllowedVal = this.allowedValues.indexOf(val || null) === 1 || this.allowedValues.map(_util.normaliseYesNo).indexOf(val ? (0, _util.normaliseYesNo)(val) : null) === 1;
    var isIndeterminate = !isFirstAllowedVal && !isSecondAllowedVal;
    this.checkbox.setIndeterminate(isIndeterminate, true);
    if (!isIndeterminate) {
      var isSelected = isFirstAllowedVal;
      this.checkbox.setSelected(isSelected, true);
    }
  }

  // Emit a change event
  this.emit("change");
};
ParameterWidget.prototype.setAutofilled = function () {
  this.autofilled = true;
  this.autofilledIcon.toggle(true);
  this.$element.css({
    "border": "1px dashed #36c"
  });
};
ParameterWidget.prototype.makeWikitext = function (pipeStyle, equalsStyle) {
  if (this.isInvalid) {
    return "";
  }
  return pipeStyle + this.name + equalsStyle + (this.value || "");
};
ParameterWidget.prototype.focusInput = function () {
  return this.input.focus();
};
var _default = ParameterWidget; // </nowiki>
exports["default"] = _default;

},{"../../util":23,"./HorizontalLayoutWidget":7}],10:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _config = _interopRequireDefault(require("../../config"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

function PrefsFormWidget(config) {
  // Configuration initialization
  config = config || {};
  // Call parent constructor
  PrefsFormWidget["super"].call(this, config);
  this.$element.addClass("rater-prefsFormWidget");
  this.layout = new OO.ui.FieldsetLayout({
    label: "设置",
    $element: this.$element
  });
  this.preferences = {
    "autostart": {
      input: new OO.ui.ToggleSwitchWidget(),
      label: "自动打开工具"
    },
    "autostartRedirects": {
      input: new OO.ui.ToggleSwitchWidget(),
      label: "重定向上自动打开"
    },
    "autostartNamespaces": {
      input: new mw.widgets.NamespacesMultiselectWidget(),
      label: "下列命名空间中自动打开"
    },
    "bypassRedirects": {
      input: new OO.ui.ToggleSwitchWidget(),
      label: "Bypass redirects to banners" // TODO
    },
    "autofillClassFromOthers": {
      input: new OO.ui.ToggleSwitchWidget(),
      label: "基于其他横幅自动填写质量"
    },
    "autofillClassFromOres": {
      input: new OO.ui.ToggleSwitchWidget(),
      label: "基于ORES指标自动填写质量"
    },
    "autofillImportance": {
      input: new OO.ui.ToggleSwitchWidget(),
      label: "自动填写低重要度"
    },
    "collapseParamsLowerLimit": {
      input: new OO.ui.NumberInputWidget({
        "min": 1
      }),
      label: "自动折叠超过此数量的参数" // review it
    },
    "watchlist": {
      input: new OO.ui.ButtonSelectWidget({
        items: [new OO.ui.ButtonOptionWidget({
          data: "preferences",
          label: "默认",
          title: "遵循参数设置中有关“编辑页面”的设置"
        }), new OO.ui.ButtonOptionWidget({
          data: "watch",
          label: "始终",
          title: "始终添加编辑的页面到监视列表"
        }), new OO.ui.ButtonOptionWidget({
          data: "nochange",
          label: "从不",
          title: "不添加编辑的页面到监视列表"
        })]
      }).selectItemByData("preferences"),
      label: "添加编辑的页面到监视列表"
    },
    "resetCache": {
      input: new OO.ui.ButtonWidget({
        label: "重置缓存",
        title: "重置缓存数据,其中包括维基专题列表和模板参数",
        flags: ["destructive"]
      })
    }
  };
  for (var prefName in this.preferences) {
    if (prefName === "autofillClassFromOres") continue; // l10n
    this.layout.addItems([new OO.ui.FieldLayout(this.preferences[prefName].input, {
      label: this.preferences[prefName].label,
      align: "right"
    })]);
  }
  this.preferences.resetCache.input.connect(this, {
    "click": "onResetCacheClick"
  });
}
OO.inheritClass(PrefsFormWidget, OO.ui.Widget);
PrefsFormWidget.prototype.setPrefValues = function (prefs) {
  var _this = this;
  var _loop = function _loop(prefName) {
    var value = prefs[prefName];
    var input = _this.preferences[prefName] && _this.preferences[prefName].input;
    switch (input && input.constructor.name) {
      case "OoUiButtonSelectWidget":
        input.selectItemByData(value);
        break;
      case "OoUiNumberInputWidget":
      case "OoUiToggleSwitchWidget":
        input.setValue(value);
        break;
      case "MwWidgetsNamespacesMultiselectWidget":
        input.clearItems();
        value.forEach(function (ns) {
          return input.addTag(ns.toString(), ns === 0 ? wgULS("条目", "條目") : _config["default"].mw.wgFormattedNamespaces[ns]);
        });
        break;
    }
  };
  for (var prefName in prefs) {
    _loop(prefName);
  }
};
PrefsFormWidget.prototype.getPrefs = function () {
  var prefs = {};
  for (var prefName in this.preferences) {
    var input = this.preferences[prefName].input;
    var value = void 0;
    switch (input.constructor.name) {
      case "OoUiButtonSelectWidget":
        value = input.findSelectedItem().getData();
        break;
      case "OoUiToggleSwitchWidget":
        value = input.getValue();
        break;
      case "OoUiNumberInputWidget":
        value = Number(input.getValue()); // widget uses strings, not numbers!
        break;
      case "MwWidgetsNamespacesMultiselectWidget":
        value = input.getValue().map(Number); // widget uses strings, not numbers!
        break;
    }
    prefs[prefName] = value;
  }
  return prefs;
};
PrefsFormWidget.prototype.onResetCacheClick = function () {
  var _this2 = this;
  OO.ui.confirm(wgULS("重置缓存后,工具将关闭并重启。已进行但未保存的更改将被放弃。", "在重設快取後,工具將自動重新啟動。此前未發布的變更將被捨棄。")).then(function (confirmed) {
    if (confirmed) {
      _this2.emit("resetCache");
    }
  });
};
var _default = PrefsFormWidget; // </nowiki>
exports["default"] = _default;

},{"../../config":18}],11:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
// <nowiki>

var SuggestionLookupTextInputWidget = function SuggestionLookupTextInputWidget(config) {
  OO.ui.TextInputWidget.call(this, config);
  OO.ui.mixin.LookupElement.call(this, config);
  this.suggestions = Array.isArray(config.suggestions) ? config.suggestions : [];
  this.$element.addClass("rater-suggestionLookupTextInputWidget");
};
OO.inheritClass(SuggestionLookupTextInputWidget, OO.ui.TextInputWidget);
OO.mixinClass(SuggestionLookupTextInputWidget, OO.ui.mixin.LookupElement);

// Set suggestion. param: Object[] with objects of the form { data: ... , label: ... }
SuggestionLookupTextInputWidget.prototype.setSuggestions = function (suggestions) {
  if (!Array.isArray(suggestions)) {
    if (suggestions != null) {
      console.warn("[Rater] SuggestionLookupTextInputWidget.prototype.setSuggestions called with a non-array value:", suggestions);
    }
    return;
  }
  this.suggestions = suggestions;
};

// Returns data, as a resolution to a promise, to be passed to #getLookupMenuOptionsFromData
SuggestionLookupTextInputWidget.prototype.getLookupRequest = function () {
  var deferred = $.Deferred().resolve(new RegExp("\\b" + mw.util.escapeRegExp(this.getValue()), "i"));
  return deferred.promise({
    abort: function abort() {}
  });
};

// ???
SuggestionLookupTextInputWidget.prototype.getLookupCacheDataFromResponse = function (response) {
  return response || [];
};

// Is passed data from #getLookupRequest, returns an array of menu item widgets 
SuggestionLookupTextInputWidget.prototype.getLookupMenuOptionsFromData = function (pattern) {
  var noRegex = function noRegex(pattern) {
    if (typeof pattern != "string") return pattern;
    return pattern.replace(/[([\]){}]/g, "\\$0");
  };
  var labelMatchesInputVal = function labelMatchesInputVal(suggestionItem) {
    return pattern.test(noRegex(suggestionItem.label)) || !noRegex(suggestionItem.label) && pattern.test(noRegex(suggestionItem.data));
  };
  var makeMenuOptionWidget = function makeMenuOptionWidget(optionItem) {
    return new OO.ui.MenuOptionWidget({
      data: optionItem.data,
      label: optionItem.label || optionItem.data
    });
  };
  return this.suggestions.filter(labelMatchesInputVal).map(makeMenuOptionWidget);
};

// Extend onLookupMenuChoose method to emit an choose event
SuggestionLookupTextInputWidget.prototype.onLookupMenuChoose = function (item) {
  // Get data
  var itemData = item.getData();
  // Simplify item data if it is an object with a name property
  if (itemData && itemData.name) {
    item.setData(itemData.name);
  }
  // First blur the input, to prevent the menu popping back up
  this.$input.blur();
  OO.ui.mixin.LookupElement.prototype.onLookupMenuChoose.call(this, item);
  this.emit("choose", itemData);
};
var _default = SuggestionLookupTextInputWidget; // </nowiki>
exports["default"] = _default;

},{}],12:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _config = _interopRequireDefault(require("../../config"));
var _SuggestionLookupTextInputWidget = _interopRequireDefault(require("./SuggestionLookupTextInputWidget"));
var _getBanners = require("../../getBanners");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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; }
// <nowiki>

function cutTitle(name) {
  // cutWikiProjectTemplateTitle
  return name.replace(/WikiProject /i, "").replace("专题", "").replace("專題", "");
}
function TopBarWidget(config) {
  var _this = this;
  // Configuration initialization
  config = $.extend({
    expanded: false,
    framed: false,
    padded: false
  }, config || {});
  // Call parent constructor
  TopBarWidget["super"].call(this, config);
  this.$overlay = config.$overlay;

  // Search box
  this.searchBox = new _SuggestionLookupTextInputWidget["default"]({
    //placeholder: wgULS("新增 WikiProject...","新增專題⋯⋯"),
    placeholder: wgULS("添加维基专题或相关模板...", "添加維基專題橫幅或相關模板⋯⋯"),
    $element: $("<div style='display:inline-block; margin:0 -1px; width:calc(100% - 55px);'>"),
    $overlay: this.$overlay
  });
  (0, _getBanners.getBannerNames)().then(function (banners) {
    var o = [banners.withRatings.map(function (bannerName) {
      return {
        label: cutTitle(bannerName),
        data: {
          name: bannerName
        }
      };
    }), banners.withoutRatings.map(function (bannerName) {
      return {
        label: cutTitle(bannerName),
        data: {
          name: bannerName,
          withoutRatings: true
        }
      };
    })].flat(1);
    var catPagesNum = o.length;
    for (var _i = 0, _Object$keys = Object.keys(banners.projectsJSON); _i < _Object$keys.length; _i++) {
      var key = _Object$keys[_i];
      var alias = banners.projectsJSON[key];
      o.push({
        label: cutTitle(key) + " - {" + alias.join(", ") + "}",
        data: {
          name: key,
          zhProjects: "values"
        }
      });
    }
    o = o.filter(function (b, i) {
      return (
        //i < catPagesNum
        i >= catPagesNum || o.findIndex(function (e) {
          return e.data.name === b.data.name;
        }) != i
      );
    }); // Remove duplicates
    return o;
  }).then(function (bannerOptions) {
    return _this.searchBox.setSuggestions(bannerOptions);
  });

  // Add button
  this.addBannerButton = new OO.ui.ButtonWidget({
    icon: "add",
    title: "新增",
    flags: "progressive",
    $element: $("<span style='float:right;margin: 0;transform: translateX(-12px);'>")
  });
  var $searchContainer = $("<div style='display:inline-block; flex-shrink:1; flex-grow:100; min-width:250px; width:50%;'>").append(this.searchBox.$element, this.addBannerButton.$element);

  // Set all classes/importances
  // in the style of a popup button with a menu (is actually a dropdown with a hidden label, because that makes the coding easier.)
  this.setAllDropDown = new OO.ui.DropdownWidget({
    icon: "tag",
    label: wgULS("全部设为...", "全部統一設置"),
    invisibleLabel: true,
    menu: {
      items: [new OO.ui.MenuSectionOptionWidget({
        label: wgULS("质量", "品質")
      }), new OO.ui.MenuOptionWidget({
        data: {
          "class": null
        },
        label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">" + wgULS("(无质量)", "(未評定)") + "</span>")
      })].concat(_toConsumableArray(_config["default"].bannerDefaults.classes.map(function (classname, i) {
        var display = _config["default"].bannerDefaultsLabel.classes[i];
        return new OO.ui.MenuOptionWidget({
          data: {
            "class": classname
          },
          label: typeof display != "undefined" ? display : classname
        });
      })), [new OO.ui.MenuSectionOptionWidget({
        label: "重要度"
      }), new OO.ui.MenuOptionWidget({
        data: {
          importance: null
        },
        label: new OO.ui.HtmlSnippet("<span style=\"color:#777\">" + wgULS("(无重要度)", "(未評定)") + "</span>")
      })], _toConsumableArray(_config["default"].bannerDefaults.importances.map(function (importance, i) {
        var display = _config["default"].bannerDefaultsLabel.importances[i];
        return new OO.ui.MenuOptionWidget({
          data: {
            importance: importance
          },
          label: typeof display != "undefined" ? display : importance
        });
      })))
    },
    $element: $("<span style=\"width:auto;display:inline-block;float:left;margin:0\" title='" + wgULS("全部设为...", "全部統一設置") + "'>"),
    $overlay: this.$overlay
  });

  // Remove all banners button
  this.removeAllButton = new OO.ui.ButtonWidget({
    icon: "trash",
    title: wgULS("全部删除", "全部刪除"),
    flags: "destructive"
  });

  // Clear all parameters button
  this.clearAllButton = new OO.ui.ButtonWidget({
    icon: "cancel",
    title: wgULS("全部清空", "全部清除"),
    flags: "destructive"
  });

  // Group the buttons together
  this.menuButtons = new OO.ui.ButtonGroupWidget({
    items: [this.removeAllButton, this.clearAllButton],
    $element: $("<span style='flex:1 0 auto;'>")
  });
  // Include the dropdown in the group
  this.menuButtons.$element.prepend(this.setAllDropDown.$element);

  // Put everything into a layout
  this.$element.addClass("rater-topBarWidget").css({
    "position": "fixed",
    "width": "100%",
    "background": "#ccc",
    "display": "flex",
    "flex-wrap": "wrap",
    "justify-content": "space-around",
    "margin": "-2px 0 0 0"
  }).append($searchContainer, this.menuButtons.$element);

  /* --- Event handling --- */

  this.searchBox.connect(this, {
    "enter": "onSearchSelect",
    "choose": "onSearchSelect"
  });
  this.addBannerButton.connect(this, {
    "click": "onSearchSelect"
  });
  this.setAllDropDown.getMenu().connect(this, {
    "choose": "onRatingChoose"
  });
  this.removeAllButton.connect(this, {
    "click": "onRemoveAllClick"
  });
  this.clearAllButton.connect(this, {
    "click": "onClearAllClick"
  });
}
OO.inheritClass(TopBarWidget, OO.ui.PanelLayout);
TopBarWidget.prototype.onSearchSelect = function (data) {
  this.emit("searchSelect", data);
};
TopBarWidget.prototype.onRatingChoose = function (item) {
  var data = item.getData();
  if (data["class"] || data["class"] === null) {
    this.emit("setClasses", data["class"]);
  }
  if (data.importance || data.importance === null) {
    this.emit("setImportances", data.importance);
  }
};
TopBarWidget.prototype.onRemoveAllClick = function () {
  this.emit("removeAll");
};
TopBarWidget.prototype.onClearAllClick = function () {
  this.emit("clearAll");
};
TopBarWidget.prototype.setDisabled = function (disable) {
  [this.searchBox, this.addBannerButton, this.setAllDropDown, this.removeAllButton, this.clearAllButton].forEach(function (widget) {
    return widget.setDisabled(disable);
  });
};
var _default = TopBarWidget; // </nowiki>
exports["default"] = _default;

},{"../../config":18,"../../getBanners":20,"./SuggestionLookupTextInputWidget":11}],13:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _api = require("../api");
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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; }
// <nowiki>

/* var incrementProgressByInterval = function() {
	var incrementIntervalDelay = 100;
	var incrementIntervalAmount = 0.1;
	var incrementIntervalMaxval = 98;
	return window.setInterval(
		incrementProgress,
		incrementIntervalDelay,
		incrementIntervalAmount,
		incrementIntervalMaxval
	);
}; */

var LoadDialog = function LoadDialog(config) {
  LoadDialog["super"].call(this, config);
};
OO.inheritClass(LoadDialog, OO.ui.Dialog);
LoadDialog["static"].name = "loadDialog";
LoadDialog["static"].title = wgULS("正在加载专题评级工具⋯⋯", "正在載入專題評級工具⋯⋯");

// Customize the initialize() function: This is where to add content to the dialog body and set up event handlers.
LoadDialog.prototype.initialize = function () {
  var _this$content$elemen;
  // Call the parent method.
  LoadDialog["super"].prototype.initialize.call(this);
  // Create a layout
  this.content = new OO.ui.PanelLayout({
    padded: true,
    expanded: false
  });
  // Create content
  this.progressBar = new OO.ui.ProgressBarWidget({
    progress: 1
  });
  this.setuptasks = [new OO.ui.LabelWidget({
    label: wgULS("加载设置...", "載入偏好設定⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }), new OO.ui.LabelWidget({
    label: wgULS("加载项目横幅列表⋯⋯", "載入專題橫幅⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }), new OO.ui.LabelWidget({
    label: wgULS("加载讨论页内容⋯⋯", "載入討論頁原始碼⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }), new OO.ui.LabelWidget({
    label: wgULS("解析讨论页模板⋯⋯", "分析討論頁模板⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }), new OO.ui.LabelWidget({
    label: wgULS("获取模板参数数据⋯⋯", "取得模板參數內容⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }), new OO.ui.LabelWidget({
    label: wgULS("检查主题页面⋯⋯", "檢查目標頁面⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }), new OO.ui.LabelWidget({
    label: wgULS("检索质量估算⋯⋯", "取得評級預測數據⋯⋯"),
    $element: $("<p style=\"display:block\">")
  }).toggle()];
  this.closeButton = new OO.ui.ButtonWidget({
    label: wgULS("关闭", "關閉")
  }).toggle();
  this.setupPromises = [];

  // Append content to layout
  (_this$content$elemen = this.content.$element).append.apply(_this$content$elemen, [this.progressBar.$element, new OO.ui.LabelWidget({
    label: wgULS("正在初始化:", "正在初始化:"),
    $element: $("<strong style=\"display:block\">")
  }).$element].concat(_toConsumableArray(this.setuptasks.map(function (widget) {
    return widget.$element;
  })), [this.closeButton.$element]));

  // Append layout to dialog
  this.$body.append(this.content.$element);

  // Connect events to handlers
  this.closeButton.connect(this, {
    "click": "onCloseButtonClick"
  });
};
LoadDialog.prototype.onCloseButtonClick = function () {
  // Close this dialog, without passing any data
  this.close();
};

// Override the getBodyHeight() method to specify a custom height (or don't to use the automatically generated height).
LoadDialog.prototype.getBodyHeight = function () {
  return this.content.$element.outerHeight(true);
};
LoadDialog.prototype.incrementProgress = function (amount, maximum) {
  var priorProgress = this.progressBar.getProgress();
  var incrementedProgress = Math.min(maximum || 100, priorProgress + amount);
  this.progressBar.setProgress(incrementedProgress);
};
LoadDialog.prototype.addTaskPromiseHandlers = function (taskPromises) {
  var _this = this;
  var onTaskDone = function onTaskDone(index) {
    // Add "Done!" to label
    var widget = _this.setuptasks[index];
    widget.setLabel(widget.getLabel() + " 完成!");
    // Increment status bar. Show a smooth transition by
    // using small steps over a short duration.
    var totalIncrement = 100 / _this.setuptasks.length; // percent
    var totalTime = 400; // milliseconds
    var totalSteps = 10;
    var incrementPerStep = totalIncrement / totalSteps;
    for (var step = 0; step < totalSteps; step++) {
      window.setTimeout(_this.incrementProgress.bind(_this), totalTime * step / totalSteps, incrementPerStep);
    }
  };
  var onTaskError = function onTaskError(index, code, info) {
    var widget = _this.setuptasks[index];
    widget.setLabel(widget.getLabel() + wgULS("失败。", "失敗⋯⋯") + (0, _api.makeErrorMsg)(code, info));
    _this.closeButton.toggle(true);
    _this.updateSize();
  };
  taskPromises.forEach(function (promise, index) {
    promise.then(function () {
      return onTaskDone(index);
    }, function (code, info) {
      return onTaskError(index, code, info);
    });
  });
};

// Use getSetupProcess() to set up the window with data passed to it at the time 
// of opening
LoadDialog.prototype.getSetupProcess = function (data) {
  var _this2 = this;
  data = data || {};
  return LoadDialog["super"].prototype.getSetupProcess.call(this, data).next(function () {
    var showOresTask = !!data.ores;
    _this2.setuptasks[6].toggle(showOresTask);
    var taskPromises = data.ores ? data.promises : data.promises.slice(0, -1);
    data.isOpened.then(function () {
      return _this2.addTaskPromiseHandlers(taskPromises);
    });
  }, this);
};

// Prevent window from closing too quickly, using getHoldProcess()
LoadDialog.prototype.getHoldProcess = function (data) {
  data = data || {};
  if (data.success) {
    // Wait a bit before processing the close, which happens automatically
    return LoadDialog["super"].prototype.getHoldProcess.call(this, data).next(800);
  }
  // No need to wait if closed manually
  return LoadDialog["super"].prototype.getHoldProcess.call(this, data);
};

// Use the getTeardownProcess() method to perform actions whenever the dialog is closed. 
LoadDialog.prototype.getTeardownProcess = function (data) {
  var _this3 = this;
  return LoadDialog["super"].prototype.getTeardownProcess.call(this, data).first(function () {
    // Perform cleanup: reset labels
    _this3.setuptasks.forEach(function (setuptask) {
      var currentLabel = setuptask.getLabel();
      setuptask.setLabel(currentLabel.slice(0, currentLabel.indexOf("...") + 3));
    });
  }, this);
};
var _default = LoadDialog; // </nowiki>
exports["default"] = _default;

},{"../api":15}],14:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _BannerWidget = _interopRequireDefault(require("./Components/BannerWidget"));
var _BannerListWidget = _interopRequireDefault(require("./Components/BannerListWidget"));
var _config = _interopRequireDefault(require("../config"));
var _api = _interopRequireWildcard(require("../api"));
var _PrefsFormWidget = _interopRequireDefault(require("./Components/PrefsFormWidget"));
var _prefs = require("../prefs");
var _Template = require("../Template");
var _TopBarWidget = _interopRequireDefault(require("./Components/TopBarWidget"));
var _util = require("../util");
var cache = _interopRequireWildcard(require("../cache"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

function MainWindow(config) {
  MainWindow["super"].call(this, config);
}
OO.inheritClass(MainWindow, OO.ui.ProcessDialog);
MainWindow["static"].name = "main";
MainWindow["static"].title = $("<span>").css({
  "font-weight": "normal"
}).append($("<a>").css({
  "font-weight": "bold"
}).attr({
  "href": mw.util.getUrl("User:Ericliu1912/維基專題評級工具"),
  "target": "_blank"
}).text("維基專題評級工具"), " (", $("<a>").attr({
  "href": mw.util.getUrl("User talk:Ericliu1912/維基專題評級工具"),
  "target": "_blank"
}).text("討論"), ") ", $("<span>").css({
  "font-size": "90%"
}).text("v" + _config["default"].script.version));
MainWindow["static"].size = "large";
MainWindow["static"].actions = [
// Primary (top right):
{
  label: "✕",
  // not using an icon since color becomes inverted, i.e. white on light-grey
  title: wgULS("关闭评级工具(放弃未保存更改)", "關閉評級工具(不儲存任何變更)"),
  flags: "primary",
  modes: ["edit", "diff", "preview"] // available when current mode isn't "prefs"
},
// Safe (top left)
{
  action: "showPrefs",
  flags: "safe",
  icon: "settings",
  title: wgULS("设置", "偏好設定"),
  modes: ["edit", "diff", "preview"] // available when current mode isn't "prefs"
},
// Others (bottom)
{
  action: "save",
  accessKey: "s",
  label: new OO.ui.HtmlSnippet("<span style='padding:0 1em;'>" + "保存" + "</span>"),
  flags: ["primary", "progressive"],
  modes: ["edit", "diff", "preview"] // available when current mode isn't "prefs"
}, {
  action: "preview",
  accessKey: "p",
  label: wgULS("显示预览", "顯示預覽"),
  modes: ["edit", "diff"] // available when current mode isn't "preview" or "prefs"
}, {
  action: "changes",
  accessKey: "v",
  label: wgULS("显示更改", "顯示變更"),
  modes: ["edit", "preview"] // available when current mode isn't "diff" or "prefs"
}, {
  action: "back",
  label: wgULS("后退", "返回"),
  modes: ["diff", "preview"] // available when current mode is "diff" or "prefs"
},
// "prefs" mode only
{
  action: "savePrefs",
  label: wgULS("更新", "儲存設定"),
  flags: ["primary", "progressive"],
  modes: "prefs"
}, {
  action: "closePrefs",
  label: "取消",
  flags: "safe",
  modes: "prefs"
}];

// Customize the initialize() function: This is where to add content to the dialog body and set up event handlers.
MainWindow.prototype.initialize = function () {
  // Call the parent method.
  MainWindow["super"].prototype.initialize.call(this);

  /* --- PREFS --- */
  this.preferences = _config["default"].defaultPrefs;

  /* --- TOP BAR --- */
  this.topBar = new _TopBarWidget["default"]({
    $overlay: this.$overlay
  });
  this.$head.css({
    "height": "73px"
  }).append(this.topBar.$element);

  /* --- FOOTER --- */
  this.oresLabel = new OO.ui.LabelWidget({
    $element: $("<span style='float:right; padding: 10px; max-width: 50%; text-align: center;'>"),
    label: $("<span>").append($("<a>").attr({
      "href": mw.util.getUrl("mw:ORES"),
      "target": "_blank"
    }).append($("<img>").css({
      "vertical-align": "text-bottom;"
    }).attr({
      "src": "//upload.wikimedia.org/wikipedia/commons/thumb/5/51/Objective_Revision_Evaluation_Service_logo.svg/40px-Objective_Revision_Evaluation_Service_logo.svg.png",
      "title": wgULS("ORES 程序提供的质量估算", "由客觀修訂評估服務(ORES)自動預測評級"),
      "alt": wgULS("ORES logo", "ORES 識別標誌"),
      "width": "20px",
      "height": "20px"
    })), " ", $("<span class='oresPrediction'>"))
  }).toggle(false);
  this.pagetypeLabel = new OO.ui.LabelWidget({
    $element: $("<span style='float:right; padding: 10px; max-width: 33.33%; text-align: center;'>")
  }).toggle(false);
  this.$foot.prepend(this.oresLabel.$element, this.pagetypeLabel.$element);

  /* --- CONTENT AREA --- */

  // Banners added dynamically upon opening, so just need a layout with an empty list
  this.bannerList = new _BannerListWidget["default"]({
    preferences: this.preferences
  });
  this.editLayout = new OO.ui.PanelLayout({
    padded: false,
    expanded: false,
    $content: this.bannerList.$element
  });

  // Preferences, filled in with current prefs upon loading.
  // TODO: Make this into a component, add fields and inputs
  this.prefsForm = new _PrefsFormWidget["default"]();
  this.prefsLayout = new OO.ui.PanelLayout({
    padded: true,
    expanded: false,
    $content: this.prefsForm.$element
  });

  // Preview, Show changes
  this.parsedContentContainer = new OO.ui.FieldsetLayout({
    label: wgULS("预览", "預覽")
  });
  this.parsedContentWidget = new OO.ui.LabelWidget({
    label: "",
    $element: $("<div>")
  });
  this.parsedContentContainer.addItems([new OO.ui.FieldLayout(this.parsedContentWidget, {
    align: "top"
  })]);
  this.parsedContentLayout = new OO.ui.PanelLayout({
    padded: true,
    expanded: false,
    $content: this.parsedContentContainer.$element
  });
  this.contentArea = new OO.ui.StackLayout({
    items: [this.editLayout, this.prefsLayout, this.parsedContentLayout],
    padded: false,
    expanded: false
  });
  this.$body.css({
    "top": "73px"
  }).append(this.contentArea.$element);

  /* --- EVENT HANDLING --- */

  this.topBar.connect(this, {
    "searchSelect": "onSearchSelect",
    "setClasses": "onSetClasses",
    "setImportances": "onSetImportances",
    "removeAll": "onRemoveAll",
    "clearAll": "onClearAll"
  });
  this.bannerList.connect(this, {
    "updatedSize": "onBannerListUpdateSize"
  });

  // Handle certain keyboard events. Requires something in the Rater window to be focused,
  // so add a tabindex to the body and it's parent container.
  this.$body.attr("tabindex", "999").parent().attr("tabindex", "999").keydown(function (event) {
    var scrollAmount;
    switch (event.which) {
      case 33:
        // page up
        scrollAmount = this.$body.scrollTop() - this.$body.height() * 0.9;
        break;
      case 34:
        // page down
        scrollAmount = this.$body.scrollTop() + this.$body.height() * 0.9;
        break;
      default:
        return;
    }
    this.$body.scrollTop(scrollAmount);
    event.preventDefault();
  }.bind(this));
  this.prefsForm.connect(this, {
    "resetCache": "onResetCache"
  });
};
MainWindow.prototype.onBannerListUpdateSize = function () {
  // Get the current scroll amount
  var scrollAmount = this.$body.scrollTop();
  // Update size (which resets the scroll to 0)
  this.updateSize();
  // Scroll to where it was before
  this.$body.scrollTop(scrollAmount);
};
MainWindow.prototype.makeDraggable = function () {
  var $frameEl = this.$element.find(".oo-ui-window-frame");
  var $handleEl = this.$element.find(".oo-ui-processDialog-location").css({
    "cursor": "move"
  });
  // Position for css translate transformations, relative to initial position
  // (which is centered on viewport when scrolled to top)
  var position = {
    x: 0,
    y: 0
  };
  var constrain = function constrain(val, minVal, maxVal) {
    if (val < minVal) return minVal;
    if (val > maxVal) return maxVal;
    return val;
  };
  var constrainX = function constrainX(val) {
    // Don't too far horizontally (leave at least 100px visible)
    var limit = window.innerWidth / 2 + $frameEl.outerWidth() / 2 - 100;
    return constrain(val, -1 * limit, limit);
  };
  var constrainY = function constrainY(val) {
    // Can't take title bar off the viewport, since it's the drag handle
    var minLimit = -1 * (window.innerHeight - $frameEl.outerHeight()) / 2;
    // Don't go too far down the page: (whole page height) - (initial position)
    var maxLimit = (document.documentElement || document).scrollHeight - window.innerHeight / 2;
    return constrain(val, minLimit, maxLimit);
  };
  var pointerdown = false;
  var dragFrom = {};
  var onDragStart = function onDragStart(event) {
    pointerdown = true;
    dragFrom.x = event.clientX;
    dragFrom.y = event.clientY;
  };
  var onDragMove = function onDragMove(event) {
    if (!pointerdown || dragFrom.x == null || dragFrom.y === null) {
      return;
    }
    var dx = event.clientX - dragFrom.x;
    var dy = event.clientY - dragFrom.y;
    dragFrom.x = event.clientX;
    dragFrom.y = event.clientY;
    position.x = constrainX(position.x + dx);
    position.y = constrainY(position.y + dy);
    $frameEl.css("transform", "translate(".concat(position.x, "px, ").concat(position.y, "px)"));
  };
  var onDragEnd = function onDragEnd() {
    pointerdown = false;
    delete dragFrom.x;
    delete dragFrom.y;
    // Make sure final positions are whole numbers
    position.x = Math.round(position.x);
    position.y = Math.round(position.y);
    $frameEl.css("transform", "translate(".concat(position.x, "px, ").concat(position.y, "px)"));
  };

  // Use pointer events if available; otherwise use mouse events
  var pointer = "PointerEvent" in window ? "pointer" : "mouse";
  $handleEl.on(pointer + "enter.raterMainWin", function () {
    return $frameEl.css("will-change", "transform");
  }); // Tell browser to optimise transform
  $handleEl.on(pointer + "leave.raterMainWin", function () {
    if (!pointerdown) $frameEl.css("will-change", "");
  }); // Remove optimisation if not dragging
  $handleEl.on(pointer + "down.raterMainWin", onDragStart);
  $("body").on(pointer + "move.raterMainWin", onDragMove);
  $("body").on(pointer + "up.raterMainWin", onDragEnd);
};

// Override the getBodyHeight() method to specify a custom height
MainWindow.prototype.getBodyHeight = function () {
  var currentlayout = this.contentArea.getCurrentItem();
  var layoutHeight = currentlayout && currentlayout.$element.outerHeight(true);
  var contentHeight = currentlayout && currentlayout.$element.children(":first-child").outerHeight(true);
  return Math.max(200, layoutHeight, contentHeight);
};

// Use getSetupProcess() to set up the window with data passed to it at the time 
// of opening
MainWindow.prototype.getSetupProcess = function (data) {
  var _this = this;
  data = data || {};
  return MainWindow["super"].prototype.getSetupProcess.call(this, data).next(function () {
    _this.makeDraggable();
    // Set up preferences
    _this.setPreferences(data.preferences);
    _this.prefsForm.setPrefValues(data.preferences);
    // Set subject page info
    _this.subjectPage = data.subjectPage;
    _this.pageInfo = {
      redirect: data.redirectTarget,
      isDisambig: data.disambig,
      hasStubtag: data.stubtag,
      isArticle: data.isArticle
    };
    // Set up edit mode banners
    _this.actions.setMode("edit");
    _this.bannerList.oresClass = data.isArticle && data.isList ? "列表" : data.ores && data.ores.prediction;
    _this.bannerList.pageInfo = _this.pageInfo;
    _this.bannerList.addItems(data.banners.map(function (bannerTemplate) {
      return new _BannerWidget["default"](bannerTemplate, {
        preferences: _this.preferences,
        $overlay: _this.$overlay,
        isArticle: _this.pageInfo.isArticle
      });
    }));
    var shellTemplateBanner = _this.bannerList.items.find(function (banner) {
      return banner.isShellTemplate;
    });
    if (shellTemplateBanner && shellTemplateBanner.shellParam1Value) {
      shellTemplateBanner.nonStandardTemplates = _this.bannerList.items.reduce(function (bannersList, curBanner) {
        return bannersList.replace(curBanner.wikitext, "");
      }, shellTemplateBanner.shellParam1Value).trim().replace(/\n+/g, "\n");
    }
    _this.bannerList.addShellTemplateIfNeeeded().syncShellTemplateWithBiographyBanner();
    // Show page type, or ORES prediction, if available
    if (_this.pageInfo.redirect) {
      _this.pagetypeLabel.setLabel(wgULS("重定向页面", "重新導向頁面")).toggle(true);
    } else if (_this.pageInfo.isDisambig) {
      _this.pagetypeLabel.setLabel(wgULS("消歧义页面", "消歧義頁面")).toggle(true);
    } else if (_this.pageInfo.isArticle && data.isGA) {
      _this.pagetypeLabel.setLabel(wgULS("优良条目", "優良條目")).toggle(true);
    } else if (_this.pageInfo.isArticle && data.isFA) {
      _this.pagetypeLabel.setLabel(wgULS("典范条目", "典範條目")).toggle(true);
    } else if (_this.pageInfo.isArticle && data.isFL) {
      _this.pagetypeLabel.setLabel("特色列表").toggle(true);
    } else if (_this.pageInfo.isArticle && data.isList) {
      _this.pagetypeLabel.setLabel("列表").toggle(true);
    } else if (data.ores) {
      _this.oresClass = data.ores.prediction;
      _this.oresLabel.toggle(true).$element.find(".oresPrediction").append(wgULS("估算:", "預測品質:"), $("<strong>").text(data.ores.prediction), "(" + data.ores.probability + ")");
    } else if (_this.pageInfo.isArticle) {
      _this.pagetypeLabel.setLabel(wgULS("条目", "條目")).toggle(true);
    } else {
      // TODO: i18n
      _this.pagetypeLabel.setLabel(_this.subjectPage.getNamespacePrefix().slice(0, -1) + wgULS("页面", "頁面")).toggle(true);
    }
    // Set props for use in making wikitext and edit summaries
    _this.talkWikitext = data.talkWikitext;
    _this.existingBannerNames = data.banners.map(function (bannerTemplate) {
      return bannerTemplate.name;
    });
    _this.talkpage = data.talkpage;
    // Force a size update to ensure eveything fits okay
    _this.updateSize();
  }, this);
};

// Set up the window it is ready: attached to the DOM, and opening animation completed
MainWindow.prototype.getReadyProcess = function (data) {
  var _this2 = this;
  data = data || {};
  return MainWindow["super"].prototype.getReadyProcess.call(this, data).next(function () {
    return _this2.topBar.searchBox.focus();
  });
};

// Use the getActionProcess() method to do things when actions are clicked
MainWindow.prototype.getActionProcess = function (action) {
  var _this3 = this;
  if (action === "showPrefs") {
    this.actions.setMode("prefs");
    this.contentArea.setItem(this.prefsLayout);
    this.topBar.setDisabled(true);
    this.updateSize();
  } else if (action === "savePrefs") {
    var updatedPrefs = this.prefsForm.getPrefs();
    return new OO.ui.Process().next((0, _prefs.setPrefs)(updatedPrefs).then(
    // Success
    function () {
      _this3.setPreferences(updatedPrefs);
      _this3.actions.setMode("edit");
      _this3.contentArea.setItem(_this3.editLayout);
      _this3.topBar.setDisabled(false);
      _this3.updateSize();
    },
    // Failure
    function (code, err) {
      return $.Deferred().reject(new OO.ui.Error($("<div>").append($("<strong style='display:block;'>").text(wgULS("保存设置失败。", "無法儲存設定。")), $("<span style='color:#777'>").text((0, _api.makeErrorMsg)(code, err)))));
    }));
  } else if (action === "clearCache") {
    return new OO.ui.Process().next(function () {
      cache.clearAllItems();
      _this3.close({
        restart: true
      });
    });
  } else if (action === "closePrefs") {
    this.actions.setMode("edit");
    this.contentArea.setItem(this.editLayout);
    this.topBar.setDisabled(false);
    this.prefsForm.setPrefValues(this.preferences);
    this.updateSize();
  } else if (action === "save") {
    return new OO.ui.Process().next(_api["default"].editWithRetry(this.talkpage.getPrefixedText(), {
      rvsection: 0
    }, function (revision) {
      return {
        section: 0,
        text: _this3.transformTalkWikitext(revision.content),
        summary: _this3.makeEditSummary(),
        watchlist: _this3.preferences.watchlist
      };
    })["catch"](function (code, err) {
      return $.Deferred().reject(new OO.ui.Error($("<div>").append($("<strong style='display:block;'>").text(wgULS("保存更改失败。", "無法儲存變更。")), $("<span style='color:#777'>").text((0, _api.makeErrorMsg)(code, err)))));
    })).next(function () {
      return _this3.close({
        success: true,
        upgradedStub: _this3.pageInfo.hasStubtag && _this3.isRatedAndNotStub()
      });
    });
  } else if (action === "preview") {
    return new OO.ui.Process().next(_api["default"].post({
      action: "parse",
      contentmodel: "wikitext",
      text: this.transformTalkWikitext(this.talkWikitext) + "\n<hr>\n" + wgULS("'''编辑摘要:''' ", "'''編輯摘要:'''") + this.makeEditSummary(),
      title: this.talkpage.getPrefixedText(),
      pst: 1
    }).then(function (result) {
      if (!result || !result.parse || !result.parse.text || !result.parse.text["*"]) {
        return $.Deferred().reject("收到空结果\n可能没有产生变化。");
      }
      var previewHtmlSnippet = new OO.ui.HtmlSnippet(result.parse.text["*"]);
      _this3.parsedContentWidget.setLabel(previewHtmlSnippet);
      _this3.parsedContentContainer.setLabel(wgULS("预览:", "預覽:"));
      _this3.actions.setMode("preview");
      _this3.contentArea.setItem(_this3.parsedContentLayout);
      _this3.topBar.setDisabled(true);
      _this3.updateSize();
    })["catch"](function (code, err) {
      return $.Deferred().reject(new OO.ui.Error($("<div>").append($("<strong style='display:block;'>").text(wgULS("显示变更失败。", "無法顯示變更。")), $("<span style='color:#777'>").text((0, _api.makeErrorMsg)(code, err)))));
    }));
  } else if (action === "changes") {
    return new OO.ui.Process().next(_api["default"].post({
      action: "compare",
      format: "json",
      fromtext: this.talkWikitext,
      fromcontentmodel: "wikitext",
      totext: this.transformTalkWikitext(this.talkWikitext),
      tocontentmodel: "wikitext",
      prop: "diff"
    }).then(function (result) {
      if (!result || !result.compare || !result.compare["*"]) {
        return $.Deferred().reject("收到空结果。\n可能没有产生变化。");
      }
      var $diff = $("<table>").addClass("diff").css("width", "100%").append($("<tr>").append($("<th>").attr({
        "colspan": "2",
        "scope": "col"
      }).css("width", "50%").text("最新修订版本"), $("<th>").attr({
        "colspan": "2",
        "scope": "col"
      }).css("width", "50%").text("新文本")), result.compare["*"], $("<tfoot>").append($("<tr>").append($("<td colspan='4'>").append($("<strong>").text(wgULS("编辑摘要:", "編輯摘要:"), _this3.makeEditSummary())))));
      _this3.parsedContentWidget.setLabel($diff);
      _this3.parsedContentContainer.setLabel("变更:");
      _this3.actions.setMode("diff");
      _this3.contentArea.setItem(_this3.parsedContentLayout);
      _this3.topBar.setDisabled(true);
      _this3.updateSize();
    })["catch"](function (code, err) {
      return $.Deferred().reject(new OO.ui.Error($("<div>").append($("<strong style='display:block;'>").text("显示更改失败。"), $("<span style='color:#777'>").text((0, _api.makeErrorMsg)(code, err)))));
    }));
  } else if (action === "back") {
    this.actions.setMode("edit");
    this.contentArea.setItem(this.editLayout);
    this.topBar.setDisabled(false);
    this.updateSize();
  } else if (!action && this.bannerList.changed) {
    // Confirm closing of dialog if there have been changes 
    if (confirm(wgULS("关闭工具将放弃未保存的更改,确认关闭?", "關閉工具將放棄未儲存的變更,確認關閉?"))) {
      this.close();
    }
  }
  return MainWindow["super"].prototype.getActionProcess.call(this, action);
};

// Use the getTeardownProcess() method to perform actions whenever the dialog is closed.
// `data` is the data passed into the window's .close() method.
MainWindow.prototype.getTeardownProcess = function (data) {
  var _this4 = this;
  return MainWindow["super"].prototype.getTeardownProcess.call(this, data).first(function () {
    _this4.bannerList.clearItems();
    _this4.topBar.searchBox.setValue("");
    _this4.contentArea.setItem(_this4.editLayout);
    _this4.topBar.setDisabled(false);
    _this4.oresLabel.toggle(false).$element.find(".oresPrediction").empty();
    _this4.pagetypeLabel.toggle(false).setLabel("");
    _this4.$element.find(".oo-ui-window-frame").css("transform", "");
    _this4.$element.find(".oo-ui-processDialog-location").off(".raterMainWin");
    $("body").off(".raterMainWin");
  });
};
MainWindow.prototype.setPreferences = function (prefs) {
  this.preferences = $.extend({}, _config["default"].defaultPrefs, prefs);
  // Applies preferences to existing items in the window:
  this.bannerList.setPreferences(this.preferences);
};
MainWindow.prototype.onResetCache = function () {
  this.executeAction("clearCache");
};
MainWindow.prototype.onSearchSelect = function (data) {
  var _this5 = this;
  this.topBar.searchBox.pushPending();
  var name = this.topBar.searchBox.getValue().trim();
  if (!name) {
    this.topBar.searchBox.popPending().focus();
    return;
  }
  var existingBanner = this.bannerList.items.find(function (banner) {
    return banner.mainText === name || banner.redirectTargetMainText === name;
  });

  // Abort and show alert if banner already exists
  if (existingBanner) {
    this.topBar.searchBox.popPending();
    return OO.ui.alert(wgULS("已有一个{{" + name + "}}横幅", "{{" + name + "}} 專題橫幅已經存在!")).then(this.searchBox.focus());
  }

  // Confirmation required for banners missing WikiProject from name, and for uncreated disambiguation talk pages
  var confirmText; // TODO: recognize it later?
  /* if (!/^[Ww](?:P|iki[Pp]roject)/.test(name)) { // i18n
  	confirmText = new OO.ui.HtmlSnippet(
  		wgULS("{{" + mw.html.escape(name) + "}} 是无法识别的WikiProject横幅。<br/>是否继续?",
  		"無法識別 {{" + mw.html.escape(name) + "}} 是否為維基專題橫幅。<br/>是否繼續操作?")
  	);
  } else if (name === "WikiProject Disambiguation" && $("#ca-talk.new").length !== 0 && this.bannerList.items.length === 0) { // TODO: l10n
  	// eslint-disable-next-line no-useless-escape
  	confirmText = "New talk pages shouldn't be created if they will only contain the \{\{WikiProject Disambiguation\}\} banner. Continue?"; // TODO: right?
  } */
  $.when(confirmText ? OO.ui.confirm(confirmText) : true).then(function (confirmed) {
    if (!confirmed) return;
    // Create Template object
    return _BannerWidget["default"].newFromTemplateName(name, data, {
      preferences: _this5.preferences,
      $overlay: _this5.$overlay,
      isArticle: _this5.pageInfo.isArticle
    }).then(function (banner) {
      _this5.bannerList.addItems([banner]);
      banner.setChanged();
      _this5.updateSize();
    });
  }).then(function () {
    return _this5.topBar.searchBox.setValue("").focus().popPending();
  });
};
MainWindow.prototype.onSetClasses = function (classVal) {
  var shellTemplate = this.bannerList.items.find(function (banner) {
    return banner.isShellTemplate;
  });
  if (shellTemplate) {
    shellTemplate.classDropdown.getMenu().selectItemByData(classVal);
    shellTemplate.classDropdown.setAutofilled(false);
  }
  this.bannerList.items.forEach(function (banner) {
    if (banner.hasClassRatings && !banner.isShellTemplate) {
      banner.classDropdown.getMenu().selectItemByData(shellTemplate ? null : classVal);
      banner.classDropdown.setAutofilled(false);
    }
  });
};
MainWindow.prototype.onSetImportances = function (importanceVal) {
  this.bannerList.items.forEach(function (banner) {
    if (banner.hasImportanceRatings) {
      banner.importanceDropdown.getMenu().selectItemByData(importanceVal);
      banner.importanceDropdown.setAutofilled(false);
    }
  });
};
MainWindow.prototype.onRemoveAll = function () {
  this.bannerList.clearItems();
};
MainWindow.prototype.onClearAll = function () {
  this.bannerList.items.forEach(function (banner) {
    return banner.onClearButtonClick();
  });
};
MainWindow.prototype.transformTalkWikitext = function (talkWikitext) {
  var _this6 = this;
  var bannersWikitext = this.bannerList.makeWikitext();
  if (!talkWikitext) {
    return bannersWikitext.trim();
  }
  // Reparse templates, in case talkpage wikitext has changed
  var talkTemplates = (0, _Template.parseTemplates)(talkWikitext, true);
  // replace existing banners wikitext with a control character
  talkTemplates.forEach(function (template) {
    if (_this6.existingBannerNames.includes(template.name)) {
      talkWikitext = talkWikitext.replace(template.wikitext, "\x01");
    }
  });
  // replace insertion point (first control character) with a different control character
  talkWikitext = talkWikitext.replace("\x01", "\x02");
  // remove other control characters
  /* eslint-disable-next-line no-control-regex */
  talkWikitext = talkWikitext.replace(/(?:\s|\n)*\x01(?:\s|\n)*/g, "");
  // split into wikitext before/after the remaining control character (and trim each section)
  var talkWikitextSections = talkWikitext.split("\x02").map(function (t) {
    return t.trim();
  });
  if (talkWikitextSections.length === 2) {
    // Found the insertion point for the banners
    return (talkWikitextSections[0] + "\n" + bannersWikitext.trim() + "\n" + talkWikitextSections[1]).trim();
  }
  // Check if there's anything beside templates
  var tempStr = talkWikitext;
  talkTemplates.forEach(function (template) {
    tempStr = tempStr.replace(template.wikitext, "");
  });
  if (/^#REDIRECT/i.test(talkWikitext) || !tempStr.trim()) {
    // Is a redirect, or everything is a template: insert at the end
    return talkWikitext.trim() + "\n" + bannersWikitext.trim();
  } else {
    // There is non-template content, so insert at the start
    return bannersWikitext.trim() + "\n" + talkWikitext.trim();
  }
};
MainWindow.prototype.isRatedAndNotStub = function () {
  var nonStubRatinggs = this.bannerList.items.filter(function (banner) {
    return banner.hasClassRatings && banner.classDropdown.getValue() && banner.classDropdown.getValue() !== "Stub";
  });
  return nonStubRatinggs.length > 0;
};
MainWindow.prototype.makeEditSummary = function () {
  var _this7 = this;
  var removedBanners = [];
  var editedBanners = [];
  var newBanners = [];
  var shortName = function shortName(name) {
    return name.replace("WikiProject ", "").replace("Subst:", "");
  };

  // Overall class/importance, if all the same
  var allClasses = (0, _util.uniqueArray)((0, _util.filterAndMap)(this.bannerList.items, function (banner) {
    return banner.hasClassRatings || banner.isShellTemplate;
  }, function (banner) {
    return banner.classDropdown.getValue();
  }));
  var overallClass = allClasses.length === 1 && allClasses[0];
  var allImportances = (0, _util.uniqueArray)((0, _util.filterAndMap)(this.bannerList.items, function (banner) {
    return banner.hasImportanceRatings;
  }, function (banner) {
    return banner.importanceDropdown.getValue();
  }));
  var overallImportance = allImportances.length === 1 && allImportances[0];
  // Don't use them unless some have changed
  var someClassesChanged = false;
  var someImportancesChanged = false;

  // removed banners:
  this.existingBannerNames.forEach(function (name) {
    var banner = _this7.bannerList.items.find(function (banner) {
      return banner.name === name || banner.bypassedName === name;
    });
    if (!banner) {
      removedBanners.push(wgULS("−", "移除") + shortName(name));
    }
  });
  // edited & new banners
  this.bannerList.items.forEach(function (banner) {
    var isNew = !banner.wikitext; // not added from wikitext on page
    if (!isNew && !banner.changed) {
      // Not changed
      return;
    }
    var newClass = banner.hasClassRatings && (isNew || banner.classChanged) && banner.classDropdown.getValue();
    if (newClass) {
      someClassesChanged = true;
    }
    if (overallClass) {
      newClass = null;
    }
    var newImportance = banner.hasImportanceRatings && (isNew || banner.importanceChanged) && banner.importanceDropdown.getValue();
    if (newImportance) {
      someImportancesChanged = true;
    }
    if (overallImportance) {
      newImportance = null;
    }
    var rating = newClass && newImportance ? newClass + "/" + newImportance : newClass || newImportance || "";
    if (rating) {
      rating = " (" + rating + ")";
    }
    if (isNew) {
      newBanners.push(wgULS("+", "新增") + shortName(banner.name) + rating);
    } else {
      editedBanners.push(shortName(banner.name) + rating);
    }
  });
  // overall rating
  var overallRating = someClassesChanged && overallClass && someImportancesChanged && overallImportance ? overallClass + "/" + overallImportance : someClassesChanged && overallClass || someImportancesChanged && overallImportance || "";
  if (overallRating) {
    overallRating = wgULS("(", "[") + overallRating + wgULS(")", "]");
  }
  return "\u8A55\u7D1A".concat(overallRating, "\uFF1A").concat([].concat(editedBanners, newBanners, removedBanners).join("、")).concat(_config["default"].script.advert);
};
var _default = MainWindow; // </nowiki>
exports["default"] = _default;

},{"../Template":3,"../api":15,"../cache":17,"../config":18,"../prefs":21,"../util":23,"./Components/BannerListWidget":4,"./Components/BannerWidget":5,"./Components/PrefsFormWidget":10,"./Components/TopBarWidget":12}],15:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.makeErrorMsg = exports["default"] = void 0;
var _config = _interopRequireDefault(require("./config"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
// <nowiki>

var API = new mw.Api({
  ajax: {
    headers: {
      "Api-User-Agent": "Rater/" + _config["default"].script.version + " ( https://en.wikipedia.org/wiki/User:Evad37/Rater )" // TODO
    }
  }
});

/* ---------- API for ORES ---------------------------------------------------------------------- */
API.getORES = function (revisionID) {
  return $.get("https://ores.wikimedia.org/v3/scores/zhwiki?models=articlequality&revids=" + revisionID);
};

/* ---------- Raw wikitext ---------------------------------------------------------------------- */
API.getRaw = function (page) {
  return $.get("https:" + _config["default"].mw.wgServer + mw.util.getUrl(page, {
    action: "raw"
  })).then(function (data) {
    if (!data) {
      return $.Deferred().reject("ok-but-empty");
    }
    return data;
  });
};

/* ---------- Edit with retry ------------------------------------------------------------------- */
/**
 * @param {String} title
 * @param {Object?} params additional params for the get request
 * @returns {Promise<Object, string>} page, starttime timestamp
 */
var getPage = function getPage(title, params) {
  return API.get($.extend({
    "action": "query",
    "format": "json",
    "curtimestamp": 1,
    "titles": title,
    "prop": "revisions|info",
    "rvprop": "content|timestamp",
    "rvslots": "main"
  }, params)).then(function (response) {
    var page = Object.values(response.query.pages)[0];
    var starttime = response.curtimestamp;
    return $.Deferred().resolve(page, starttime);
  });
};

/**
 * @param {Object} page details object from API
 * @param {string} starttime timestamp
 * @param {Function} transform callback that prepares the edit:
 *  {Object} simplifiedPage => {Object|Promise<Object>} edit params
 * @returns {Promise<Object>} params for edit query
 */
var processPage = function processPage(page, starttime, transform) {
  var basetimestamp = page.revisions && page.revisions[0].timestamp;
  var simplifiedPage = {
    pageid: page.pageid,
    missing: page.missing === "",
    redirect: page.redirect === "",
    categories: page.categories,
    ns: page.ns,
    title: page.title,
    content: page.revisions && page.revisions[0].slots.main["*"]
  };
  return $.when(transform(simplifiedPage)).then(function (editParams) {
    return $.extend({
      action: "edit",
      title: page.title,
      // Protect against errors and conflicts
      assert: "user",
      basetimestamp: basetimestamp,
      starttimestamp: starttime
    }, editParams);
  });
};

/** editWithRetry
 * 
 * Edits a page, resolving edit conflicts, and retrying edits that fail. The
 * tranform function may return a rejected promise if the page should not be
 * edited; the @returns {Promise} will will be rejected with the same rejection
 * values.
 * 
 * Note: Unlike [mw.Api#Edit], a missing page will be created, unless the
 * transform callback includes the "nocreate" param.
 * 
 * [mw.Api#Edit]: <https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Api.plugin.edit>
 * 
 * @param {String} title page to be edited
 * @param {Object|null} getParams additional params for the get request
 * @param {Function} transform callback that prepares the edit:
 *  {Object} simplifiedPage => {Object|Promise<Object>} params for API editing
 * @returns {Promise<object>} promise, resolved on success, rejected if
 *  page was not edited
 */
API.editWithRetry = function (title, getParams, transform) {
  return getPage(title, getParams).then(
  // Succes: process the page
  function (page, starttime) {
    return processPage(page, starttime, transform);
  },
  // Failure: try again
  function () {
    return getPage(title, getParams).then(processPage, transform);
  }).then(function (editParams) {
    return API.postWithToken("csrf", editParams)["catch"](function (errorCode) {
      if (errorCode === "editconflict") {
        // Try again, starting over
        return API.editWithRetry(title, getParams, transform);
      }
      // Try again
      return API.postWithToken("csrf", editParams);
    });
  });
};
var makeErrorMsg = function makeErrorMsg(first, second) {
  var code, xhr, message;
  if (_typeof(first) === "object" && typeof second === "string") {
    // Errors from $.get being rejected (ORES & Raw wikitext)
    var errorObj = first.responseJSON && first.responseJSON.error;
    if (errorObj) {
      // Got an api-specific error code/message
      code = errorObj.code;
      message = errorObj.message;
    } else {
      xhr = first;
    }
  } else if (typeof first === "string" && _typeof(second) === "object") {
    // Errors from mw.Api object
    var mwErrorObj = second.error;
    if (mwErrorObj) {
      // Got an api-specific error code/message
      code = errorObj.code;
      message = errorObj.info;
    } else if (first === "ok-but-empty") {
      code = null;
      message = "Got an empty response from the server";
    } else {
      xhr = second && second.xhr;
    }
  }
  if (code && message) {
    return "API error ".concat(code, ": ").concat(message);
  } else if (message) {
    return "API error: ".concat(message);
  } else if (xhr) {
    return "HTTP error ".concat(xhr.status);
  } else if (typeof first === "string" && first !== "error" && typeof second === "string" && second !== "error") {
    return "Error ".concat(first, ": ").concat(second);
  } else if (typeof first === "string" && first !== "error") {
    return "Error: ".concat(first);
  } else {
    return "Unknown API error";
  }
};
exports.makeErrorMsg = makeErrorMsg;
var _default = API; // </nowiki>
exports["default"] = _default;

},{"./config":18}],16:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _config = _interopRequireDefault(require("./config"));
var _prefs = require("./prefs");
var _api = _interopRequireWildcard(require("./api"));
var _setup = _interopRequireDefault(require("./setup"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

var autoStart = function autoStart() {
  return (0, _prefs.getPrefs)().then(function (prefs) {
    // Check if pref is turned off
    if (!prefs.autostart) {
      return;
    }
    // Check if pref is turned off for redirects, and current page is a redirect
    if (!prefs.autostartRedirects && window.location.search.includes("redirect=no")) {
      return;
    }
    // Check if viewing diff/history/old version
    if (/(action|diff|oldid)/.test(window.location.search)) {
      return;
    }
    var subjectTitle = mw.Title.newFromText(_config["default"].mw.wgPageName).getSubjectPage();
    // Check if subject page is the main page
    if (subjectTitle.getPrefixedText() === "Main Page") {
      return;
    }
    // Check subject page namespace
    if (prefs.autostartNamespaces && prefs.autostartNamespaces.length && !prefs.autostartNamespaces.includes(_config["default"].mw.wgNamespaceNumber)) {
      return;
    }

    // If talk page does not exist, can just autostart
    if ($("#ca-talk.new").length) {
      return (0, _setup["default"])();
    }

    /* Check templates present on talk page. Fetches indirectly transcluded templates, so will find
    	Template:WPBannerMeta (and its subtemplates). But some banners such as MILHIST don't use that
    	meta template, so we also have to check for template titles containg 'WikiProject'
    */
    var talkTitle = mw.Title.newFromText(_config["default"].mw.wgPageName).getTalkPage();
    return _api["default"].get({
      action: "query",
      format: "json",
      prop: "templates",
      titles: talkTitle.getPrefixedText(),
      tlnamespace: "10",
      tllimit: "500",
      indexpageids: 1
    }).then(function (result) {
      var id = result.query.pageids;
      var templates = result.query.pages[id].templates;
      if (!templates) {
        return (0, _setup["default"])();
      }
      var hasWikiproject = templates.some(function (template) {
        return /(WikiProject|WPBanner)/.test(template.title);
      });
      if (!hasWikiproject) {
        return (0, _setup["default"])();
      }
    }, function (code, jqxhr) {
      // Silently ignore failures (just log to console)
      console.warn("[Rater] Error while checking whether to autostart." + (code == null) ? "" : " " + (0, _api.makeErrorMsg)(code, jqxhr));
      return $.Deferred().reject();
    });
  });
};
var _default = autoStart; // </nowiki>
exports["default"] = _default;

},{"./api":15,"./config":18,"./prefs":21,"./setup":22}],17:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.clearAllItems = exports.clearInvalidItems = exports.clearItemIfInvalid = exports.read = exports.write = void 0;
var _util = require("./util");
// <nowiki>

/** write
 * @param {String} key
 * @param {Array|Object} val
 * @param {Number} staleDays Number of days after which the data becomes stale (usable, but should
 *  be updated for next time).
 * @param {Number} expiryDays Number of days after which the cached data may be deleted.
 */
var write = function write(key, val, staleDays, expiryDays) {
  try {
    var defaultStaleDays = 1;
    var defaultExpiryDays = 30;
    var millisecondsPerDay = 24 * 60 * 60 * 1000;
    var staleDuration = (staleDays || defaultStaleDays) * millisecondsPerDay;
    var expiryDuration = (expiryDays || defaultExpiryDays) * millisecondsPerDay;
    var stringVal = JSON.stringify({
      value: val,
      staleDate: new Date(Date.now() + staleDuration).toISOString(),
      expiryDate: new Date(Date.now() + expiryDuration).toISOString()
    });
    localStorage.setItem("Rater-" + key, stringVal);
  } catch (e) {} // eslint-disable-line no-empty
};
/** read
 * @param {String} key
 * @returns {Array|Object|String|Null} Cached array or object, or empty string if not yet cached,
 *          or null if there was error.
 */
exports.write = write;
var read = function read(key) {
  var val;
  try {
    var stringVal = localStorage.getItem("Rater-" + key);
    if (stringVal !== "") {
      val = JSON.parse(stringVal);
    }
  } catch (e) {
    console.log("[Rater] error reading " + key + " from localStorage cache:");
    console.log("\t" + e.name + " message: " + e.message + (e.at ? " at: " + e.at : "") + (e.text ? " text: " + e.text : ""));
  }
  return val || null;
};
exports.read = read;
var isRaterKey = function isRaterKey(key) {
  return key && key.indexOf("Rater-") === 0;
};
var clearItemIfInvalid = function clearItemIfInvalid(key) {
  if (!isRaterKey(key)) {
    return;
  }
  var item = read(key.replace("Rater-", ""));
  var isInvalid = !item || !item.expiryDate || (0, _util.isAfterDate)(item.expiryDate);
  if (isInvalid) {
    localStorage.removeItem(key);
  }
};
exports.clearItemIfInvalid = clearItemIfInvalid;
var clearInvalidItems = function clearInvalidItems() {
  // Loop backwards as localStorage length will decrease as items are removed
  for (var i = localStorage.length; i >= 0; i--) {
    setTimeout(clearItemIfInvalid, 100, localStorage.key(i));
  }
};
exports.clearInvalidItems = clearInvalidItems;
var clearAllItems = function clearAllItems() {
  // Loop backwards as localStorage length will decrease as items are removed
  for (var i = localStorage.length; i >= 0; i--) {
    var key = localStorage.key(i);
    if (isRaterKey(key)) {
      localStorage.removeItem(key);
    }
  }
};

// </nowiki>
exports.clearAllItems = clearAllItems;

},{"./util":23}],18:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
// <nowiki>
var packagejson = require("../package.json");
var version = packagejson.version;

// A global object that stores all the page and user configuration and settings
var config = {
  // Script info
  script: {
    // Advert to append to edit summaries
    advert: "[由[[User:Ericliu1912/維基專題評級工具#".concat(version,"|維基專題評級工具]]輔助]"),
    version: version
  },
  // Default preferences, if user subpage raterPrefs.json does not exist
  defaultPrefs: {
    "autostart": false,
    "autostartRedirects": false,
    "autostartNamespaces": [0],
    "minForShell": 1,
    "bypassRedirects": true,
    "autofillClassFromOthers": true,
    "autofillClassFromOres": true,
    "autofillImportance": true,
    "collapseParamsLowerLimit": 6,
    "watchlist": "preferences"
  },
  // MediaWiki configuration values
  mw: mw.config.get(["skin", "wgPageName", "wgNamespaceNumber", "wgUserName", "wgFormattedNamespaces", "wgMonthNames", "wgRevisionId", "wgScriptPath", "wgServer", "wgCategories", "wgIsMainPage"]),
  bannerDefaults: {
    classes: ["FA", "FL", "A", "GA", "B", "C", "start", "stub", "list"],
    importances: ["top", "high", "mid", "low"],
    extendedClasses: ["category", "draft", "file", "FM", "portal", "project", "template",
    //"Bplus",
    "future", "current", "disambig", "NA", "redirect"
    //"Book"
    ],
    extendedImportances: ["top", "high", "mid", "low", "bottom", "NA"]
  },
  bannerDefaultsLabel: {
    // i18n. this must be synchronized with the wiki and the above definition
    classes: wgULS(["典范条目", "特色列表", "甲", "优良", "乙", "丙", "初", "小作品", "列表"], ["典範條目", "特色列表", "甲", "優良", "乙", "丙", "初", "小作品", "列表"]),
    importances: wgULS(["极高", "高", "中", "低"], ["極高", "高", "中", "低"]),
    extendedClasses: wgULS(["分类", "草稿", "文件", "典范媒体", "主题", "项目", "模板",
    //"Bplus",
    "未来", "动态", "消歧义", "不适用", "重定向"
    //"Book"
    ], ["分類", "草稿", "檔案", "典範媒體", "主題", "計畫", "模板",
    //"Bplus",
    "未來", "動態", "消歧義", "不適用", "重新導向"]),
    extendedImportances: wgULS(["极高", "高", "中", "低", "极低", "不适用"], ["極高", "高", "中", "低", "極低", "不適用"])
  },
  customBanners: {},
  shellTemplates: [
  // TODO: check it
  "WikiProject banner shell", "WikiProjectBanners", "WikiProject Banners", "WPB", "WPBS", "Wikiprojectbannershell", "WikiProject Banner Shell", "Wpb", "WPBannerShell", "Wpbs", "Wikiprojectbanners", "WP Banner Shell", "WP banner shell", "Bannershell", "Wikiproject banner shell", "WikiProject Banners Shell", "WikiProjectBanner Shell", "WikiProjectBannerShell", "WikiProject BannerShell", "WikiprojectBannerShell", "WikiProject banner shell/redirect", "WikiProject Shell", "Banner shell", "Scope shell", "Project shell", "WikiProject banner"],
  defaultParameterData: {
    "auto": {
      "label": {
        "en": "Auto-rated",
        "zh": "自动评级"
      },
      "description": {
        "en": "Automatically rated by a bot. Allowed values: ['yes'].",
        "zh": "机器人完成的自动评级。允许的值:['yes']。"
      },
      "autovalue": "yes"
    },
    "listas": {
      "label": {
        "en": "List as",
        "zh": "排序索引"
      },
      "description": {
        "en": "Sortkey for talk page",
        "zh": "讨论页的排序索引"
      }
    },
    "small": {
      "label": {
        "en": "Small?",
        "zh": "小型?"
      },
      "description": {
        "en": "Display a small version. Allowed values: ['yes'].",
        "zh": "显示小型版本。允许的值:['yes']。"
      },
      "autovalue": "yes"
    },
    "attention": {
      "label": {
        "en": "Attention required?",
        "zh": "需要关注?"
      },
      "description": {
        "en": "Immediate attention required. Allowed values: ['yes'].",
        "zh": "需要立即关注。允许的值:['yes']。"
      },
      "autovalue": "yes"
    },
    "needs-image": {
      "label": {
        "en": "Needs image?",
        "zh": "需要图像?"
      },
      "description": {
        "en": "Request that an image or photograph of the subject be added to the article. Allowed values: ['yes'].",
        "zh": "条目需要本主题的图像或照片。允许的值:['yes']。"
      },
      "aliases": ["needs-photo"],
      "autovalue": "yes",
      "suggested": true
    },
    "needs-infobox": {
      "label": {
        "en": "Needs infobox?",
        "zh": "需要信息框?"
      },
      "description": {
        "en": "Request that an infobox be added to the article. Allowed values: ['yes'].",
        "zh": "条目需要一个信息框。允许的值:['yes']。"
      },
      "aliases": ["needs-photo" // TODO: why?
      ],
      "autovalue": "yes",
      "suggested": true
    }
  }
};
var _default = config; // </nowiki>
exports["default"] = _default;

},{"../package.json":1}],19:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
// <nowiki>

// Attribution: Diff styles based on <https://en.wikipedia.org/wiki/Wikipedia:AutoWikiBrowser/style.css>
var styles = "table.diff, td.diff-otitle, td.diff-ntitle { table-layout: auto !important;; }\ntd.diff-otitle, td.diff-ntitle { text-align: center; }\ntd.diff-marker { text-align: right; font-weight: bold; font-size: 1.25em; }\ntd.diff-lineno { font-weight: bold; }\ntd.diff-addedline, td.diff-deletedline, td.diff-context { font-size: 88%; vertical-align: top; white-space: -moz-pre-wrap; white-space: pre-wrap; }\ntd.diff-addedline, td.diff-deletedline { border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; }\ntd.diff-addedline { border-color: #a3d3ff; }\ntd.diff-deletedline { border-color: #ffe49c; }\ntd.diff-context { background: #f3f3f3; color: #333333; border-style: solid; border-width: 1px 1px 1px 4px; border-color: #e6e6e6; border-radius: 0.33em; }\n.diffchange { font-weight: bold; text-decoration: none; }\ntable.diff {\n    border: none;\n    width: 98%; border-spacing: 4px;\n    table-layout: fixed; /* Ensures that colums are of equal width */\n}\ntd.diff-addedline .diffchange, td.diff-deletedline .diffchange { border-radius: 0.33em; padding: 0.25em 0; }\ntd.diff-addedline .diffchange {\tbackground: #d8ecff; }\ntd.diff-deletedline .diffchange { background: #feeec8; }\ntable.diff td {\tpadding: 0.33em 0.66em; }\ntable.diff col.diff-marker { width: 2%; }\ntable.diff col.diff-content { width: 48%; }\ntable.diff td div {\n    /* Force-wrap very long lines such as URLs or page-widening char strings. */\n    word-wrap: break-word;\n    /* As fallback (FF<3.5, Opera <10.5), scrollbars will be added for very wide cells\n        instead of text overflowing or widening */\n    overflow: auto;\n}" + // Override OOUI window manager preventing background scrolling/interaction
"html body.rater-mainWindow-open {\n\tposition: unset;\n\toverflow: unset;\n}\nhtml body.rater-mainWindow-open .oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-active {\n    position: static;\n    padding: 0;\n}" + // Increase z-index, to be above skin menus etc; smooth transition for dragging (transform:translate)
"html body.rater-mainWindow-open .oo-ui-dialog.oo-ui-window-active > div {\n    z-index: 110;\n    transition: all 0.25s ease-out 0s, transform 0s !important\n}\n" + // Ensure close dialog is visible
"html body.rater-mainWindow-open #mw-teleport-target {\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right:0;\n}\n";
var _default = styles; // </nowiki>
exports["default"] = _default;

},{}],20:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getBannerNames = void 0;
var _api = _interopRequireWildcard(require("./api"));
var _util = require("./util");
var cache = _interopRequireWildcard(require("./cache"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
// <nowiki>

var cacheBanners = function cacheBanners(banners) {
  cache.write("banners", banners, 2, 60);
};

// The code snippet from https://wiki.zwnes.eu.org/wiki/User:Chiefwei/rater/rater.js
var raterData = {};
var dataurl = "";
function getRaterData(kind) {
  if (kind === "default") {
    dataurl = mw.config.get("wgScript") + "?action=raw&ctype=application/json&maxage=86400&title=User:Chiefwei/rater/" + kind + ".js";
  } else {
    dataurl = mw.config.get("wgScript") + "?action=raw&ctype=application/json&maxage=86400&title=User:Sz-iwbot/rater/" + kind + ".json";
  }
  if (raterData[kind] === void null) {
    try {
      $.ajax({
        "url": dataurl,
        "dataType": "json",
        "async": false,
        "success": function success(data) {
          raterData[kind] = data;
        },
        "error": function error(xhr, message) {
          mw.log.error(new Error(message));
        }
      });
    } catch (e) {
      alert("获取评级工具“" + kind + "”数据错误:" + e.message + "。评级工具可能无法正常工作。");
      raterData[kind] = null;
    }
  }
  return raterData[kind];
}

/**
 * Gets banners/options from the Api
 * 
 * @returns {Promise} Resolved with: banners object, bannerOptions array
 */
var getListOfBannersFromApi = function getListOfBannersFromApi() {
  var finishedPromise = $.Deferred();
  var querySkeleton = {
    action: "query",
    format: "json",
    list: "categorymembers",
    cmprop: "title",
    cmnamespace: "10",
    cmlimit: "500"
  };
  var categories = [
  // i18n configure
  {
    title: "Category:含质量评级的专题横幅",
    abbreviation: "withRatings",
    banners: [],
    processed: $.Deferred()
  }, {
    title: "Category:不含质量评级的专题横幅",
    abbreviation: "withoutRatings",
    banners: [],
    processed: $.Deferred()
  } /*,
    {
    title: "Category:WikiProject banner wrapper templates", // TODO: missing and review is needed
    abbreviation: "wrappers",
    banners: [],
    processed: $.Deferred()
    },
    {
    title: "Category:WikiProject banner templates not based on WPBannerMeta", // TODO: same as above
    abbreviation: "notWPBM",
    banners: [],
    processed: $.Deferred()
    },
    {
    title: "Category:Inactive WikiProject banners", // TODO: same as above
    abbreviation: "inactive",
    banners: [],
    processed: $.Deferred()
    }*/];
  var processQuery = function processQuery(result, catIndex) {
    if (!result.query || !result.query.categorymembers) {
      // No results
      // TODO: error or warning ********
      finishedPromise.reject();
      return;
    }

    // Gather titles into array - excluding "Template:" prefix
    var resultTitles = result.query.categorymembers.map(function (info) {
      return info.title.slice(9);
    });
    Array.prototype.push.apply(categories[catIndex].banners, resultTitles);

    // Continue query if needed
    if (result["continue"]) {
      doApiQuery($.extend(categories[catIndex].query, result["continue"]), catIndex);
      return;
    }
    categories[catIndex].processed.resolve();
  };
  var doApiQuery = function doApiQuery(q, catIndex) {
    _api["default"].get(q).done(function (result) {
      processQuery(result, catIndex);
    }).fail(function (code, jqxhr) {
      console.warn("[Rater] " + (0, _api.makeErrorMsg)(code, jqxhr, "Could not retrieve pages from [[:" + q.cmtitle + "]]"));
      finishedPromise.reject();
    });
  };
  categories.forEach(function (cat, index, arr) {
    cat.query = $.extend({
      "cmtitle": cat.title
    }, querySkeleton);
    $.when(arr[index - 1] && arr[index - 1].processed || true).then(function () {
      doApiQuery(cat.query, index);
    });
  });
  categories[categories.length - 1].processed.then(function () {
    var banners = {};
    categories.forEach(function (catObject) {
      banners[catObject.abbreviation] = catObject.banners;
    });
    banners["projectsJSON"] = getRaterData("projects");
    finishedPromise.resolve(banners);
  });
  return finishedPromise;
};

/**
 * Gets banners from cache, if there and not too old
 * 
 * @returns {Promise} Resolved with banners object
 */
var getBannersFromCache = function getBannersFromCache() {
  var cachedBanners = cache.read("banners"); //TODO
  if (!cachedBanners || !cachedBanners.value || !cachedBanners.staleDate) {
    return $.Deferred().reject();
  }
  if ((0, _util.isAfterDate)(cachedBanners.staleDate)) {
    // Update in the background; still use old list until then  
    getListOfBannersFromApi().then(cacheBanners);
  }
  return $.Deferred().resolve(cachedBanners.value);
};

/**
 * Gets banner names, grouped by type (withRatings, withoutRatings, wrappers, notWPBM)
 * @returns {Promise<Object>} Object of string arrays keyed by type (withRatings, withoutRatings, wrappers, notWPBM)
 */
var getBannerNames = function getBannerNames() {
  return getBannersFromCache().then(function (banners) {
    // Ensure all keys exist
    if (!banners.withRatings || !banners.withoutRatings || !banners.projectsJSON /* || !banners.wrappers || !banners.notWPBM || !banners.inactive || !banners.wir*/) {
      getListOfBannersFromApi().then(cacheBanners);
      return $.extend({
        withRatings: [],
        withoutRatings: [],
        projectsJSON: [] /* , wrappers: [], notWPBM: [], inactive: [], wir: []*/
      }, banners);
    }
    // Success: pass through
    return banners;
  })["catch"](function () {
    // Failure: get from Api, then cache them
    var bannersPromise = getListOfBannersFromApi();
    bannersPromise.then(cacheBanners);
    return bannersPromise;
  });
};

// </nowiki>
exports.getBannerNames = getBannerNames;

},{"./api":15,"./cache":17,"./util":23}],21:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.setPrefs = exports.getPrefs = exports["default"] = void 0;
var _api = _interopRequireDefault(require("./api"));
var _util = require("./util");
var _config = _interopRequireDefault(require("./config"));
var cache = _interopRequireWildcard(require("./cache"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

var prefsPage = "User:".concat(mw.config.get("wgUserName"), "/raterPrefs.json");
var writePrefsToCache = function writePrefsToCache(prefs) {
  return cache.write("prefs", prefs, 1 / 24 / 60 * 1,
  // 1 min
  1 / 24 / 60 * 1 // 1 min
  );
};
var getPrefsFromApi = function getPrefsFromApi() {
  if (mw.config.get("wgUserName") == null) {
    return $.Deferred().resolve({});
  }
  return _api["default"].get({
    "action": "query",
    "format": "json",
    "prop": "revisions",
    "titles": prefsPage,
    "rvprop": "content",
    "rvslots": "main"
  }).then(function (response) {
    var page = response.query.pages[Object.keys(response.query.pages)[0]];
    if (!page.pageid || page.missing === "") {
      return _config["default"].defaultPrefs;
    }
    var prefs;
    try {
      prefs = JSON.parse(page.revisions[0].slots.main["*"]);
    } catch (e) {
      return $.Deferred().reject("JSON-parsing-error", e); // not work?
    }
    writePrefsToCache(prefs);
    return prefs;
  });
};
var getPrefsFromCache = function getPrefsFromCache() {
  var cachedPrefs = cache.read("prefs");
  if (!cachedPrefs || !cachedPrefs.value || !cachedPrefs.staleDate || (0, _util.isAfterDate)(cachedPrefs.staleDate)) {
    // No cached value, or is too old
    return $.Deferred().reject();
  }
  return $.Deferred().resolve(cachedPrefs.value);
};
var getPrefs = function getPrefs() {
  return getPrefsFromCache().then(
  // Success: pass through (first param only)
  function (prefs) {
    return $.Deferred().resolve(prefs);
  },
  // Failure: get from Api
  function () {
    return getPrefsFromApi();
  });
};

/**
 * 
 * @param {Object} updatedPrefs object with key:value pairs for preferences json.
 */
exports.getPrefs = getPrefs;
var setPrefs = function setPrefs(updatedPrefs) {
  return _api["default"].editWithRetry(prefsPage, null, function () {
    return {
      "text": JSON.stringify(updatedPrefs),
      "summary": "保存偏好設定" + _config["default"].script.advert
    };
  }).then(function () {
    return writePrefsToCache(updatedPrefs);
  });
};
exports.setPrefs = setPrefs;
var _default = {
  get: getPrefs,
  set: setPrefs
}; // </nowiki>
exports["default"] = _default;

},{"./api":15,"./cache":17,"./config":18,"./util":23}],22:[function(require,module,exports){
"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _config = _interopRequireDefault(require("./config"));
var _api = _interopRequireDefault(require("./api"));
var _Template = require("./Template");
var _getBanners = require("./getBanners");
var cache = _interopRequireWildcard(require("./cache"));
var _windowManager = _interopRequireDefault(require("./windowManager"));
var _prefs = require("./prefs");
var _util = require("./util");
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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; }
// <nowiki>

var setupRater = function setupRater(clickEvent) {
  if (clickEvent) {
    clickEvent.preventDefault();
  }
  var setupCompletedPromise = $.Deferred();
  var currentPage = mw.Title.newFromText(_config["default"].mw.wgPageName);
  var talkPage = currentPage && currentPage.getTalkPage();
  var subjectPage = currentPage && currentPage.getSubjectPage();
  var subjectIsArticle = _config["default"].mw.wgNamespaceNumber <= 1;

  // Get preferences (task 0)
  var prefsPromise = (0, _prefs.getPrefs)();

  // Get lists of all banners (task 1)
  var bannersPromise = (0, _getBanners.getBannerNames)();

  // Load talk page (task 2)
  var loadTalkPromise = _api["default"].get({
    action: "query",
    prop: "revisions",
    rvprop: "content",
    rvsection: "0",
    titles: talkPage.getPrefixedText(),
    indexpageids: 1
  }).then(function (result) {
    var id = result.query.pageids;
    var wikitext = id < 0 ? "" : result.query.pages[id].revisions[0]["*"];
    return wikitext;
  });
  var curAllTemplateAlias = null;
  var getAllTemplateAlias = function getAllTemplateAlias(JSON) {
    if (curAllTemplateAlias != null) return curAllTemplateAlias; // cache
    var o = [];
    o = o.concat(Object.keys(JSON));
    for (var _i = 0, _Object$keys = Object.keys(JSON); _i < _Object$keys.length; _i++) {
      var key = _Object$keys[_i];
      var alias = JSON[key];
      o.push(alias);
    }
    curAllTemplateAlias = o;
    return curAllTemplateAlias;
  };
  // Parse talk page for banners (task 3)
  var parseTalkPromise = loadTalkPromise.then(function (wikitext) {
    return (0, _Template.parseTemplates)(wikitext, true);
  }) // Get all templates
  .then(function (templates) {
    return templates.filter(function (template) {
      return template.getTitle() !== null;
    });
  }) // Filter out invalid templates (e.g. parser functions)
  .then(function (templates) {
    return (0, _Template.getWithRedirectTo)(templates);
  }) // Check for redirects
  .then(function (templates) {
    return bannersPromise.then(function (allBanners) {
      // Get list of all banner templates
      return (0, _util.filterAndMap)(templates,
      // Filter out non-banners
      function (template) {
        if (template.isShellTemplate()) {
          return true;
        }
        var mainText = template.redirectTarget ? template.redirectTarget.getMainText() : template.getTitle().getMainText();
        return allBanners.withRatings.includes(mainText) || allBanners.withoutRatings.includes(mainText) || getAllTemplateAlias(allBanners.projectsJSON).includes(mainText);
      },
      // Set additional properties if needed
      function (template) {
        var mainText = template.redirectTarget ? template.redirectTarget.getMainText() : template.getTitle().getMainText();
        if (allBanners.withoutRatings.includes(mainText)) {
          template.withoutRatings = true;
        }
        if (!(new RegExp("WikiProject ", "i").test(mainText) || mainText.includes("专题") || mainText.includes("專題"))) {
          template.nonBanner = true;
        }
        return template;
      });
    });
  });

  // Retrieve and store classes, importances, and TemplateData (task 4)
  var templateDetailsPromise = parseTalkPromise.then(function (templates) {
    // Wait for all promises to resolve
    return $.when.apply(null, [].concat(_toConsumableArray(templates.map(function (template) {
      return template.isShellTemplate() ? null : template.setClassesAndImportances();
    })), _toConsumableArray(templates.map(function (template) {
      return template.setParamDataAndSuggestions();
    })))).then(function () {
      // Add missing required/suggested values
      templates.forEach(function (template) {
        return template.addMissingParams();
      });
      // Return the now-modified templates
      return templates;
    });
  });

  // Check subject page features (task 5) - but don't error out if request fails
  var subjectPageCheckPromise = _api["default"].get({
    action: "query",
    format: "json",
    formatversion: "2",
    prop: "categories",
    titles: subjectPage.getPrefixedText(),
    redirects: 1
    //,clcategories: ["Category:全部消歧義頁面", "Category:全部小作品", "Category:優良條目", "Category:典范条目", "Category:特色列表"] // i18n; disabling it will return all categories, the hasCategoryRegex require it.
  }).then(function (response) {
    if (!response || !response.query || !response.query.pages) {
      return null;
    }
    var redirectTarget = response.query.redirects && response.query.redirects[0].to || false;
    if (redirectTarget || !subjectIsArticle) {
      return {
        redirectTarget: redirectTarget
      };
    }
    var page = response.query.pages[0];
    var hasCategory = function hasCategory(category) {
      return page.categories && page.categories.find(function (cat) {
        return cat.title === "Category:" + category;
      });
    };
    var hasCategoryRegex = function hasCategoryRegex(regex) {
      return page.categories && page.categories.find(function (cat) {
        return regex.test(cat.title);
      });
    };
    return {
      // i18n
      redirectTarget: redirectTarget,
      disambig: hasCategory("全部消歧義頁面"),
      stubtag: hasCategory("全部小作品"),
      isGA: hasCategory("優良條目"),
      isFA: hasCategory("典范条目"),
      isFL: hasCategory("特色列表"),
      isList: !hasCategory("特色列表") && hasCategoryRegex(/^Category:.*列表.*/)
    };
  })["catch"](function () {
    return null;
  }); // Failure ignored

  // Retrieve rating from ORES (task 6, only needed for articles) - but don't error out if request fails
  var shouldGetOres = false; //( subjectIsArticle ); // TODO: Don't need to get ORES for redirects or disambigs
  if (false || shouldGetOres) {
    var latestRevIdPromise = !currentPage.isTalkPage() ? $.Deferred().resolve(_config["default"].mw.wgRevisionId) : _api["default"].get({
      action: "query",
      format: "json",
      prop: "revisions",
      titles: subjectPage.getPrefixedText(),
      rvprop: "ids",
      indexpageids: 1
    }).then(function (result) {
      if (result.query.redirects) {
        return false;
      }
      var id = result.query.pageids;
      var page = result.query.pages[id];
      if (page.missing === "") {
        return false;
      }
      if (id < 0) {
        return $.Deferred().reject();
      }
      return page.revisions[0].revid;
    });
    var oresPromise = latestRevIdPromise.then(function (latestRevId) {
      if (!latestRevId) {
        return false;
      }
      return _api["default"].getORES(latestRevId).then(function (result) {
        var data = result.zhwiki.scores[latestRevId].articlequality;
        if (data.error) {
          return $.Deferred().reject(data.error.type, data.error.message);
        }
        var prediction = data.score.prediction;
        var probabilities = data.score.probability;
        if (prediction === "FA" || prediction === "GA") {
          return {
            prediction: "B or higher",
            probability: ((probabilities.FA + probabilities.GA + probabilities.B) * 100).toFixed(1) + "%"
          };
        }
        return {
          prediction: prediction,
          probability: (probabilities[prediction] * 100).toFixed(1) + "%"
        };
      })["catch"](function () {
        return null;
      }); // Failure ignored;
    });
  }

  // Open the load dialog
  var isOpenedPromise = $.Deferred();
  var loadDialogWin = _windowManager["default"].openWindow("loadDialog", {
    promises: [bannersPromise, loadTalkPromise, parseTalkPromise, templateDetailsPromise, subjectPageCheckPromise, shouldGetOres && oresPromise],
    ores: shouldGetOres,
    isOpened: isOpenedPromise
  });
  loadDialogWin.opened.then(isOpenedPromise.resolve);
  $.when(prefsPromise, loadTalkPromise, templateDetailsPromise, subjectPageCheckPromise, shouldGetOres && oresPromise).then(
  // All succeded
  function (preferences, talkWikitext, banners, subjectPageCheck, oresPredicition) {
    var result = {
      success: true,
      talkpage: talkPage,
      subjectPage: subjectPage,
      talkWikitext: talkWikitext,
      banners: banners,
      preferences: preferences,
      isArticle: subjectIsArticle
    };
    if (subjectPageCheck) {
      result = _objectSpread({}, result, {}, subjectPageCheck);
    }
    if (oresPredicition && subjectPageCheck && !subjectPageCheck.isGA && !subjectPageCheck.isFA && !subjectPageCheck.isFL) {
      result.ores = oresPredicition;
    }
    _windowManager["default"].closeWindow("loadDialog", result);
  }); // Any failures are handled by the loadDialog window itself

  // On window closed, check data, and resolve/reject setupCompletedPromise
  loadDialogWin.closed.then(function (data) {
    if (data && data.success) {
      // Got everything needed: Resolve promise with this data
      setupCompletedPromise.resolve(data);
    } else if (data && data.error) {
      // There was an error: Reject promise with error code/info
      setupCompletedPromise.reject(data.error.code, data.error.info);
    } else {
      // Window closed before completion: resolve promise without any data
      setupCompletedPromise.resolve(null);
    }
    cache.clearInvalidItems();
  });
  return setupCompletedPromise;
};
var _default = setupRater; // </nowiki>
exports["default"] = _default;

},{"./Template":3,"./api":15,"./cache":17,"./config":18,"./getBanners":20,"./prefs":21,"./util":23,"./windowManager":24}],23:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.mostFrequent = mostFrequent;
exports.uniqueArray = uniqueArray;
exports.classMask = classMask;
exports.importanceMask = importanceMask;
exports.normaliseYesNo = exports.filterAndMap = exports.isAfterDate = void 0;
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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; }
// <nowiki>

// Various utility functions and objects that might be used in multiple places

var isAfterDate = function isAfterDate(dateString) {
  return new Date(dateString) < new Date();
};
exports.isAfterDate = isAfterDate;
var yesWords = [
// TODO: L10
"add", "added", "affirm", "affirmed", "include", "included", "on", "true", "yes", "y", "1"];
var noWords = [
// TODO: L10
"decline", "declined", "exclude", "excluded", "false", "none", "not", "no", "n", "off", "omit", "omitted", "remove", "removed", "0"];
var normaliseYesNo = function normaliseYesNo(val) {
  if (val == null) {
    return val;
  }
  var trimmedLcVal = val.trim().toLowerCase();
  if (yesWords.includes(trimmedLcVal)) {
    return "yes";
  } else if (noWords.includes(trimmedLcVal)) {
    return "no";
  } else {
    return trimmedLcVal;
  }
};

/**
 * 
 * @param {Array} array 
 * @param {Function} filterPredicate (currentVal, currentIndex, array) => {boolean}
 * @param {Function} mapTransform (currentVal, currentIndex, array) => {any}
 * @returns {Array}
 */
exports.normaliseYesNo = normaliseYesNo;
var filterAndMap = function filterAndMap(array, filterPredicate, mapTransform) {
  return array.reduce(function (accumulated, currentVal, currentIndex) {
    if (filterPredicate(currentVal, currentIndex, array)) {
      return [].concat(_toConsumableArray(accumulated), [mapTransform(currentVal, currentIndex, array)]);
    }
    return accumulated;
  }, []);
};

/**
 * 
 * @param {string[]|number[]} array 
 * @returns {string|null} item with the highest frequency
 * e.g. `mostFrequent(["apple", "apple", "orange"])` returns `"apple"`
 */
exports.filterAndMap = filterAndMap;
function mostFrequent(array) {
  if (!array || !Array.isArray(array) || array.length === 0) return null;
  var map = {};
  var mostFreq = null;
  array.forEach(function (item) {
    map[item] = (map[item] || 0) + 1;
    if (mostFreq === null || map[item] > map[mostFreq]) {
      mostFreq = item;
    }
  });
  return mostFreq;
}

/**
 * 
 * @param {string[]|number[]} array 
 * @returns {string[]|number[]} array with only unique values
 * e.g. `uniqueArray(["apple", "apple", "orange"])` returns `["apple", "orange"]`
 */
function uniqueArray(array) {
  if (!array || !Array.isArray(array) || array.length === 0) return [];
  var seen = {};
  var unique = [];
  array.forEach(function (item) {
    if (!seen[item]) {
      unique.push(item);
      seen[item] = true;
    }
  });
  return unique;
}
function classMask(classVal) {
  // TODO: check it
  if (!classVal) {
    return classVal;
  }
  switch (classVal.toLowerCase()) {
    case "fa":
    case "fl":
    case "a":
    case "ga":
    case "b":
    case "c":
    case "na":
    case "fm":
    case "al":
    case "bl":
    case "cl":
      return classVal.toUpperCase();
    case "File":
    case "image":
    case "img":
      return "file";
    case "Category":
    case "cat":
    case "categ":
      return "category";
    case "disambiguation":
    case "Disambig":
    case "disamb":
    case "dab":
      return "disambig";
    case "Redirect":
    case "redir":
    case "red":
      return "redirect";
    case "Template":
    case "temp":
    case "tpl":
      return "template";
    case "bplus":
    case "b+":
      return "Bplus";
    default:
      return classVal;
  }
}
function importanceMask(importance) {
  if (!importance) {
    return importance;
  }
  if (importance.toLowerCase() === "na") {
    return "NA";
  }
  return importance.slice(0, 1).toUpperCase() + importance.slice(1).toLowerCase();
}

// </nowiki>

},{}],24:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;
var _LoadDialog = _interopRequireDefault(require("./Windows/LoadDialog"));
var _MainWindow = _interopRequireDefault(require("./Windows/MainWindow"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
// <nowiki>

var factory = new OO.Factory();

// Register window constructors with the factory.
factory.register(_LoadDialog["default"]);
factory.register(_MainWindow["default"]);
var manager = new OO.ui.WindowManager({
  "factory": factory
});
$(document.body).append(manager.$element);
var _default = manager; // </nowiki>
exports["default"] = _default;

},{"./Windows/LoadDialog":13,"./Windows/MainWindow":14}]},{},[2])

});
// </nowiki>