bgm-wiki-rev-diff

show diff between bgm.tv wiki versions

目前為 2020-04-25 提交的版本,檢視 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        bgm-wiki-rev-diff
// @namespace   https://trim21.me/
// @version     0.0.6
// @author      Trim21 <[email protected]>
// @source      https://github.com/Trim21/bgm-wiki-rev-diff
// @license     MIT
// @match       https://bgm.tv/subject/*/edit
// @match       https://bangumi.tv/subject/*/edit
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @require     https://cdn.jsdelivr.net/npm/[email protected]/bundles/js/diff2html.min.js
// @require     https://cdn.jsdelivr.net/npm/[email protected]/dist/diff.min.js
// @grant       GM_xmlhttpRequest
// @connect     bgm.tv
// @connect     bangumi.tv
// @run-at      document-end
// @description show diff between bgm.tv wiki versions
// ==/UserScript==

/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ 		}
/******/ 	};
/******/
/******/ 	// define __esModule on exports
/******/ 	__webpack_require__.r = function(exports) {
/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 		}
/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
/******/ 	};
/******/
/******/ 	// create a fake namespace object
/******/ 	// mode & 1: value is a module id, require it
/******/ 	// mode & 2: merge all properties of value into the ns
/******/ 	// mode & 4: return value when already ns object
/******/ 	// mode & 8|1: behave like require
/******/ 	__webpack_require__.t = function(value, mode) {
/******/ 		if(mode & 1) value = __webpack_require__(value);
/******/ 		if(mode & 8) return value;
/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ 		var ns = Object.create(null);
/******/ 		__webpack_require__.r(ns);
/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ 		return ns;
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = "e6Wu");
/******/ })
/************************************************************************/
/******/ ({

/***/ "HIjm":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const parser_1 = __webpack_require__("MI+m");
const utils_1 = __webpack_require__("j7bY");
const differ_1 = __webpack_require__("epE4");
const ui_1 = __webpack_require__("Va9c");
const model_1 = __webpack_require__("kvtW");
function compare(revID1, revID2) {
    ui_1.clear();
    ui_1.show('<h2>loading versions...</h2>');
    const rev1 = parser_1.getRevInfo(revID1);
    const rev2 = parser_1.getRevInfo(revID2);
    const p1 = utils_1.request(rev1.url);
    const p2 = utils_1.request(rev2.url);
    Promise.all([p1, p2]).then(values => {
        const contents = [];
        for (const page of values) {
            contents.push(parser_1.parseRevDetails(page.responseText));
        }
        const c1 = new model_1.Comment(rev1, contents[0]);
        const c2 = new model_1.Comment(rev2, contents[1]);
        const d = differ_1.diff(c1, c2);
        const rendered = ui_1.render(d);
        ui_1.show(rendered);
    }).catch(() => {
        ui_1.show('<h2 style="color:red">loading versions error</h2>');
    });
}
exports.compare = compare;


/***/ }),

/***/ "MI+m":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const $ = __webpack_require__("xeH2");
const model_1 = __webpack_require__("kvtW");
function parseRevDetails(html) {
    const jq = $(html);
    const rawInfo = jq.find('#subject_infobox').val().toString();
    const title = jq.find('input[name="subject_title"]').val().toString();
    const description = jq.find('textarea#subject_summary').val().toString();
    return new model_1.RevDetail(title, rawInfo, description);
}
exports.parseRevDetails = parseRevDetails;
function parseRevEl(el) {
    const date = el.find('a').first().html();
    const revEL = el.find('a.l:contains("恢复")');
    const revCommentEl = el.find('span.comment');
    let comment = '';
    if (revCommentEl.length) {
        comment = revCommentEl.html();
        comment = comment.substring(1, comment.length - 1);
    }
    const revHref = revEL.attr('href');
    const revID = revHref.split('/').pop();
    return {
        id: revID,
        comment,
        date,
        url: revHref,
    };
}
exports.parseRevEl = parseRevEl;
function getRevs() {
    const revs = [];
    $('#pagehistory li').each(function () {
        const el = $(this);
        revs.push(parseRevEl(el));
    });
    return revs;
}
function getRevInfo(revID) {
    for (const rev of getRevs()) {
        if (rev.id === revID) {
            return rev;
        }
    }
}
exports.getRevInfo = getRevInfo;


/***/ }),

/***/ "O5RH":
/***/ (function(module, exports) {

module.exports = Diff;

/***/ }),

/***/ "Va9c":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const Diff2Html = __webpack_require__("znBf");
const $ = __webpack_require__("xeH2");
function render(diff) {
    return Diff2Html.html(diff);
}
exports.render = render;
function show(html) {
    $('#show-trim21-cn').html(html);
}
exports.show = show;
function clear() {
    $('#show-trim21-cn').html('');
}
exports.clear = clear;


/***/ }),

/***/ "e6Wu":
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("xeH2");
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _parser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("MI+m");
/* harmony import */ var _parser__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_parser__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _compare__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__("HIjm");
/* harmony import */ var _compare__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_compare__WEBPACK_IMPORTED_MODULE_2__);




function main () {
  console.log('start bgm wiki rev differ UserScript')
  initUI()
}

function initUI () {
  jquery__WEBPACK_IMPORTED_MODULE_0__('#columnInSubjectA').prepend('<div id=show-trim21-cn></dev>')
  jquery__WEBPACK_IMPORTED_MODULE_0__('#pagehistory li').each(function () {
    const el = jquery__WEBPACK_IMPORTED_MODULE_0__(this)
    const rev = Object(_parser__WEBPACK_IMPORTED_MODULE_1__["parseRevEl"])(el)
    el.prepend(`<input type="checkbox" class="rev-trim21-cn" name="rev" label="select to compare" value="${rev.id}">`)
  })
  jquery__WEBPACK_IMPORTED_MODULE_0__('#columnInSubjectA span.text').append('<a href="#;" id="compare-trim21-cn" tar class="l"> > 比较选中的版本</a>')
  jquery__WEBPACK_IMPORTED_MODULE_0__('#compare-trim21-cn').on('click', function () {
    const selectedRevs = getSelectedVersion()
    Object(_compare__WEBPACK_IMPORTED_MODULE_2__["compare"])(selectedRevs[0], selectedRevs[1])
  })
  jquery__WEBPACK_IMPORTED_MODULE_0__('head').append('<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css" />')
}

function getSelectedVersion () {
  const selectedVersion = []
  const selectedRev = jquery__WEBPACK_IMPORTED_MODULE_0__('.rev-trim21-cn:checked')
  if (selectedRev.length < 2) {
    window.alert('请选中两个版本进行比较')
  }
  if (selectedRev.length > 2) {
    window.alert('只能比较两个版本')
  }
  selectedRev.each(function () {
    const el = jquery__WEBPACK_IMPORTED_MODULE_0__(this)
    selectedVersion.push(el.val())
  })
  selectedVersion.reverse()
  return selectedVersion
}

main()


/***/ }),

/***/ "epE4":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const Diff = __webpack_require__("O5RH");
function diff(rev1, rev2) {
    return `${titleDiff(rev1, rev2)}\n${infoDiff(rev1, rev2)}\n${descriptionDiff(rev1, rev2)}`;
}
exports.diff = diff;
function titleDiff(rev1, rev2) {
    if (rev1.details.title === rev2.details.title) {
        return '';
    }
    return Diff.createTwoFilesPatch('title', 'title', rev1.details.title, rev2.details.title, rev1.rev.date, rev2.rev.date);
}
function infoDiff(rev1, rev2) {
    if (rev1.details.rawInfo === rev2.details.rawInfo) {
        return '';
    }
    return Diff.createTwoFilesPatch('info', 'info', rev1.details.rawInfo, rev2.details.rawInfo, rev1.rev.date, rev2.rev.date);
}
function descriptionDiff(rev1, rev2) {
    if (rev1.details.description === rev2.details.description) {
        return '';
    }
    return Diff.createTwoFilesPatch('description', 'description', rev1.details.description, rev2.details.description, rev1.rev.date, rev2.rev.date);
}


/***/ }),

/***/ "j7bY":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
function request(url) {
    return new Promise((resolve) => {
        // @ts-ignore
        window.GM_xmlhttpRequest({
            url,
            // @ts-ignore
            onload: function ({ responseText, }) {
                resolve({ responseText });
            }
        });
    });
}
exports.request = request;


/***/ }),

/***/ "kvtW":
/***/ (function(module, exports, __webpack_require__) {

"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
class RevDetail {
    constructor(title, rawInfo, description) {
        this.title = title;
        this.rawInfo = rawInfo;
        this.description = description;
    }
}
exports.RevDetail = RevDetail;
class Rev {
}
exports.Rev = Rev;
class Comment {
    constructor(rev, detail) {
        this.rev = rev;
        this.details = detail;
    }
}
exports.Comment = Comment;


/***/ }),

/***/ "xeH2":
/***/ (function(module, exports) {

module.exports = $;

/***/ }),

/***/ "znBf":
/***/ (function(module, exports) {

module.exports = Diff2Html;

/***/ })

/******/ });