MCP :: SRG Mapper

Apply SRG mappings to code.

当前为 2015-01-02 提交的版本,查看 最新版本

  1. /*jslint devel: true, browser: true, regexp: true, continue: true, plusplus: true, maxerr: 50, indent: 4 */
  2. /*global unsafeWindow: false, $: false, toastr: false, JSZip: false */
  3. /*global GM_setValue: false, GM_getValue: false, GM_listValues: false, GM_deleteValue: false, GM_addStyle: false, GM_getResourceText: false, GM_xmlhttpRequest: false */
  4.  
  5. // ==UserScript==
  6. // @name MCP :: SRG Mapper
  7. // @namespace Lunatrius
  8. // @description Apply SRG mappings to code.
  9. // @author Lunatrius <lunatrius@gmail.com>
  10. // @include https://github.com/MinecraftForge/FML*
  11. // @include https://github.com/MinecraftForge/MinecraftForge*
  12. // @include https://github.com/MinecraftForge/FML/pull/*/files
  13. // @include https://github.com/MinecraftForge/MinecraftForge/pull/*/files
  14. // @include https://gist.github.com/*/*
  15. // @include http://paste.ee/*
  16. // @include http://paste.feed-the-beast.com/view/*
  17. // @include http://pastebin.com/*
  18. // @exclude http://paste.ee/
  19. // @exclude http://pastebin.com/
  20. // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js
  21. // @require https://raw.githubusercontent.com/defunkt/jquery-pjax/master/jquery.pjax.js
  22. // @require https://raw.githubusercontent.com/Stuk/jszip/master/dist/jszip.min.js
  23. // @require https://raw.githubusercontent.com/CodeSeven/toastr/master/build/toastr.min.js
  24. // @require http://harvesthq.github.io/chosen/chosen.jquery.js
  25. // @resource toast_css https://raw.githubusercontent.com/CodeSeven/toastr/master/build/toastr.min.css
  26. // @resource chosen_css http://harvesthq.github.io/chosen/chosen.css
  27. // @version 0.1.6
  28. // @grant GM_setValue
  29. // @grant GM_getValue
  30. // @grant GM_listValues
  31. // @grant GM_deleteValue
  32. // @grant GM_addStyle
  33. // @grant GM_getResourceText
  34. // @grant GM_xmlhttpRequest
  35. // @grant unsafeWindow
  36. // @license MIT
  37. // ==/UserScript==
  38.  
  39. (function (window) {
  40. "use strict";
  41.  
  42. if (window !== window.top) {
  43. return;
  44. }
  45.  
  46. $.fn.outerHtml = function () {
  47. return $("<tmp></tmp>").append(this).html();
  48. };
  49.  
  50. var mapper = {
  51. baseList: "http://export.mcpbot.bspk.rs/",
  52. baseMapping: "http://files.minecraftforge.net/maven/de/oceanlabs/mcp/",
  53. regexParse: /(func_[0-9]+_[a-z]+_?|field_[0-9]+_[a-z]+_?|p_i?[0-9]+_[0-9]+_?),([^,]+),/i,
  54. regexReplace: /\b(?:func_[0-9]+_[a-z]+_?|field_[0-9]+_[a-z]+_?|p_i?[0-9]+_[0-9]+_?)\b/gi,
  55.  
  56. regexMapping: /^(\d+(?:\.\d+)+):((stable)(?:_nodoc)?_(\d+)|(snapshot)(?:_nodoc)?_(\d{8}))$/,
  57.  
  58. mappingList: [],
  59. currentMapping: null,
  60. mappings: {},
  61.  
  62. updateIntervalList: 1000 * 3600 * 12,
  63. updateIntervalMapping: 1000 * 3600 * 24 * 365,
  64.  
  65. settings: {
  66. "github.com": {
  67. tag: "li",
  68. insert: "div.container>ul.pagehead-actions",
  69. container: "#files table tr td.blob-code, .file .type-diff table tr td.blob-code, .inline-review-comment table tr td.blob-code"
  70. },
  71. "gist.github.com": {
  72. tag: "li",
  73. insert: "div.container>div.title-actions-bar>ul.pagehead-actions",
  74. container: ".files .file-data .line-data div.line"
  75. },
  76. "paste.ee": {
  77. tag: "span",
  78. insert: ".container>.row>.row>.col-sm-12:has(#download)",
  79. container: "#paste-content ol li div",
  80. css: [
  81. "#remap_container { float: right; }",
  82. "#remap_container a { cursor: pointer; }"
  83. ].join("\n")
  84. },
  85. "paste.feed-the-beast.com": {
  86. tag: "span",
  87. insert: "div.col-lg-12>div.detail.by:eq(0)",
  88. container: ".CodeMirror ol li div",
  89. css: [
  90. "#remap_container { float: right; }",
  91. "#remap_container a { cursor: pointer; }"
  92. ].join("\n")
  93. },
  94. "pastebin.com": {
  95. tag: "span",
  96. insert: "#code_frame #code_buttons",
  97. container: "#code_frame ol li span",
  98. css: [
  99. "#remap_container { float: right; margin-top: 4pt; }",
  100. "#remap_container a { cursor: pointer; }"
  101. ].join("\n")
  102. }
  103. },
  104.  
  105. setCurrentMapping: function (mc, type, version) {
  106. if (type === undefined && version === undefined) {
  107. var mapping = this.parseMapping(mc);
  108. this.currentMapping = mapping[0] ? mapping[0] + ":" + mapping[1] + "_" + mapping[2] : null;
  109. } else {
  110. this.currentMapping = mc + ":" + type + "_" + version;
  111. }
  112.  
  113. return this.currentMapping;
  114. },
  115.  
  116. parseMapping: function (mapping) {
  117. var m = mapping && mapping.match(/^(\d+(?:\.\d+)+):((stable)(?:_nodoc)?_(\d+)|(snapshot)(?:_nodoc)?_(\d{8}))$/);
  118. return m ? [m[1], m[3] || m[5], m[4] || m[6]] : [null, null, null];
  119. },
  120.  
  121. set: function (key, val) {
  122. GM_setValue(key, JSON.stringify(val));
  123. },
  124.  
  125. get: function (key, def) {
  126. try {
  127. return JSON.parse(GM_getValue(key, def)) || def;
  128. } catch (ignore) {}
  129. return def;
  130. },
  131.  
  132. list: function () {
  133. return GM_listValues();
  134. },
  135.  
  136. del: function (key) {
  137. GM_deleteValue(key);
  138. },
  139.  
  140. clean: function () {
  141. $.each(this.list(), function (index, value) {
  142. this.del(value);
  143. }.bind(this));
  144. },
  145.  
  146. time: function () {
  147. return new Date().getTime();
  148. },
  149.  
  150. init: function () {
  151. if (window !== window.top) {
  152. return;
  153. }
  154.  
  155. var css = [
  156. GM_getResourceText("toast_css"),
  157. GM_getResourceText("chosen_css")
  158. ];
  159.  
  160. this.settings = this.settings[location.host];
  161. if (!this.settings) {
  162. GM_addStyle(css.join("\n"));
  163. toastr.info("No settings for " + location.host + "... :(");
  164. return this;
  165. }
  166.  
  167. if (this.settings.css) {
  168. css = css.concat(this.settings.css);
  169. }
  170.  
  171. GM_addStyle(css.join("\n"));
  172.  
  173. toastr.options.closeButton = true;
  174. toastr.options.showMethod = "slideDown";
  175. toastr.options.hideMethod = "slideUp";
  176. toastr.options.preventDuplicates = true;
  177.  
  178. this.setCurrentMapping(this.get("selected", ""));
  179.  
  180. this.mappingList = this.get("mappings", []);
  181.  
  182. $.each(this.list(), function (index, version) {
  183. if (this.regexMapping.test(version) && $.inArray(version, this.mappingList) === -1) {
  184. toastr.warning("Removing old mappings...<br/>" + version);
  185. this.del(version);
  186. this.del(version + "_update");
  187. }
  188. }.bind(this));
  189.  
  190. try {
  191. this.main();
  192. } catch (e) {
  193. console.log(e);
  194. }
  195.  
  196. delete this.init;
  197.  
  198. return this;
  199. },
  200.  
  201. main: function () {
  202. this.update();
  203.  
  204. $("<" + this.settings.tag + ">")
  205. .attr("id", "remap_container")
  206. .append($("<select></select>").change(this.changeMapping.bind(this)))
  207. .append(" ")
  208. .append($("<a></a>").addClass("minibutton").text("Remap").click(this.remap.bind(this)))
  209. .prependTo(this.settings.insert);
  210.  
  211. this.populateMappings();
  212. },
  213.  
  214. update: function () {
  215. if (this.get("mappings_update", 0) + this.updateIntervalList < this.time()) {
  216. toastr.info("Fetching mapping list...");
  217. this.query(this.baseList + "versions.json?limit=5", this.saveMappingList.bind(this), this.updateMapping.bind(this));
  218. return true;
  219. } else {
  220. return this.updateMapping();
  221. }
  222. },
  223.  
  224. updateMapping: function () {
  225. if (this.setCurrentMapping(this.currentMapping) !== null) {
  226. if (this.get(this.currentMapping + "_update", 0) + this.updateIntervalMapping < this.time()) {
  227. toastr.info("Fetching mappings: " + this.currentMapping);
  228. var mapping = this.parseMapping(this.currentMapping);
  229. this.query(this.mappingUrl(mapping[0], mapping[1], mapping[2]), this.saveMappings.bind(this), function () {
  230. $(this.settings.container).each(this.doRemap.bind(this));
  231. }.bind(this));
  232. return true;
  233. } else {
  234. this.mappings = this.get(this.currentMapping, []);
  235. return false;
  236. }
  237. } else {
  238. toastr.info("No mappings selected.");
  239. }
  240. return false;
  241. },
  242.  
  243. changeMapping: function (event) {
  244. this.setCurrentMapping($(event.target).val());
  245. this.set("selected", this.currentMapping);
  246. },
  247.  
  248. remap: function (event) {
  249. var target = $(event.target);
  250.  
  251. if (target.hasClass("selected")) {
  252. target.removeClass("selected");
  253.  
  254. $(".processed").removeClass("processed").find("u[title]").each(this.undoRemap);
  255. } else {
  256. target.addClass("selected");
  257.  
  258. this.setCurrentMapping($("#remap_container select").val());
  259. this.mappings = this.get(this.currentMapping, []);
  260.  
  261. if (!this.update()) {
  262. $(this.settings.container).each(this.doRemap.bind(this));
  263. }
  264. }
  265.  
  266. $("#remap_container .chosen-container").css("z-index", 9001).css("display", target.hasClass("selected") ? "none" : "");
  267. },
  268.  
  269. undoRemap: function (index, node) {
  270. $(node).replaceWith($(node).attr("title"));
  271. },
  272.  
  273. doRemap: function (index, node) {
  274. node = $(node);
  275. if (!node.hasClass("processed")) {
  276. var html = node.html();
  277. if (this.regexReplace.test(html)) {
  278. node.html(html.replace(this.regexReplace, this.applyRemap.bind(this))).addClass("processed");
  279. }
  280. }
  281. },
  282.  
  283. applyRemap: function (token) {
  284. var mcpname, node;
  285.  
  286. mcpname = this.mappings[token];
  287. node = $("<u></u>").attr("title", token);
  288.  
  289. if (!mcpname) {
  290. node.css("font-style", "italic");
  291. }
  292.  
  293. return node.text(mcpname || token).outerHtml();
  294. },
  295.  
  296. populateMappings: function () {
  297. $("#remap_container select").html("");
  298. $.each(this.mappingList, function (index, version) {
  299. $("<option></option>").val(version).text(version).appendTo("#remap_container select");
  300. });
  301. $("#remap_container select").val(this.currentMapping).chosen();
  302. },
  303.  
  304. saveMappingList: function (data, callback) {
  305. var json = JSON.parse(data);
  306. this.mappingList = [];
  307.  
  308. $.each(json, function (mc, data) {
  309. $.each(data, function (type, versions) {
  310. $.each(versions, function (index, version) {
  311. this.mappingList.push(mc + ":" + type + "_" + version);
  312. }.bind(this));
  313. }.bind(this));
  314. }.bind(this));
  315.  
  316. this.set("mappings", this.mappingList);
  317. this.set("mappings_update", this.time());
  318.  
  319. toastr.success("Saved mapping list.");
  320.  
  321. this.populateMappings();
  322.  
  323. if (callback) {
  324. callback();
  325. }
  326. },
  327.  
  328. mappingUrl: function (mc, type, version) {
  329. return this.baseMapping + "mcp_" + type + "_nodoc/" + version + "-" + mc + "/mcp_" + type + "_nodoc-" + version + "-" + mc + ".zip";
  330. },
  331.  
  332. saveMappings: function (data, callback) {
  333. var zip, parse;
  334.  
  335. zip = JSZip(data);
  336.  
  337. parse = function (index, line) {
  338. var m = line.match(this.regexParse);
  339. if (m && m.length === 3) {
  340. this.mappings[m[1]] = m[2];
  341. }
  342. };
  343.  
  344. this.mappings = {};
  345. $.each(zip.file("methods.csv").asText().split("\n"), parse.bind(this));
  346. $.each(zip.file("fields.csv").asText().split("\n"), parse.bind(this));
  347. $.each(zip.file("params.csv").asText().split("\n"), parse.bind(this));
  348.  
  349. this.set(this.currentMapping, this.mappings);
  350. this.set(this.currentMapping + "_update", this.time());
  351.  
  352. toastr.success("Saved mappings.");
  353.  
  354. if (callback) {
  355. callback();
  356. }
  357. },
  358.  
  359. query: function (url, callback, innerCallback) {
  360. GM_xmlhttpRequest({
  361. url: url,
  362. method: "GET",
  363. // should work but doesn't...
  364. // responseType: "arraybuffer",
  365. overrideMimeType: "text/plain; charset=x-user-defined",
  366. onload: function (response) {
  367. try {
  368. callback(response.response, innerCallback);
  369. } catch (e) {
  370. toastr.error("Something went wrong!<br/>" + e.message);
  371. }
  372. }.bind(this)
  373. });
  374. }
  375. }.init();
  376. }(unsafeWindow));

QingJ © 2025

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