Add comment searching support in Bilibili.
// ==UserScript== // @name Bilibili 评论搜索 // @name:en Bilibili Comment Search // @name:zh Bilibili 评论搜索 // @namespace npm/vite-plugin-monkey // @version 0.2.0 // @author pacexy <[email protected]> // @description 让 Bilibili 支持评论搜索。 // @description:en Add comment searching support in Bilibili. // @description:zh 让 Bilibili 支持评论搜索。 // @license MIT // @icon https://www.bilibili.com/favicon.ico // @homepage https://github.com/pacexy/userscript-bilibili-comment-search#readme // @homepageURL https://github.com/pacexy/userscript-bilibili-comment-search#readme // @source https://github.com/pacexy/userscript-bilibili-comment-search.git // @supportURL https://github.com/pacexy/userscript-bilibili-comment-search/issues // @match *://www.bilibili.com/video/av* // @match *://www.bilibili.com/bangumi/play/ep* // @match *://www.bilibili.com/bangumi/play/ss* // @match *://www.bilibili.com/video/BV* // @require https://cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js // ==/UserScript== (e=>{const o=document.createElement("style");o.dataset.source="vite-plugin-monkey",o.textContent=e,document.head.append(o)})(" #comment-search-root{float:right}#comment-search-root button{margin-left:auto;border:none;padding:4px 8px;border-radius:4px}#comment-search-root dialog[open]{display:block}#comment-search-root dialog{display:none;width:800px;margin:auto;padding:1em;border-radius:8px;border:none;outline:none;overflow:hidden}#comment-search-root dialog .header{display:flex;align-items:center}#comment-search-root dialog .header h1{font-size:15px;color:var(--text1)}#comment-search-root dialog .header h1 span{color:var(--text3)}#comment-search-root dialog input{padding:5px 10px;border:1px solid var(--Ga1);border-radius:4px;background-color:var(--bg3);color:var(--text1);outline:none;width:100%;margin-top:20px}#comment-search-root dialog .note{color:var(--text3);margin:10px 0}#comment-search-root dialog .comment-tree{height:500px;overflow:auto;overscroll-behavior:contain}#comment-search-root .comment-item{display:flex}#comment-search-root .comment-item-avatar{border-radius:50%;background-color:var(--Ga1);margin-right:10px;flex-shrink:0}#comment-search-root .comment-item-username{font-size:12px;font-weight:700;margin-bottom:4px;color:#61666d;margin-right:12px}#comment-search-root .comment-item-message{font-size:14px;color:var(--text1)}#comment-search-root .comment-item-highlight{background-color:#f8eec2}#comment-search-root .comment-item-time{color:var(--text3);margin-top:4px} "); (function (require$$0, require$$0$1) { 'use strict'; function getDefaultExportFromCjs(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; } var jsxRuntime = { exports: {} }; var reactJsxRuntime_production_min = {}; /** * @license React * react-jsx-runtime.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var f = require$$0, k = Symbol.for("react.element"), l = Symbol.for("react.fragment"), m$1 = Object.prototype.hasOwnProperty, n = f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner, p = { key: true, ref: true, __self: true, __source: true }; function q(c, a, g) { var b, d = {}, e = null, h = null; void 0 !== g && (e = "" + g); void 0 !== a.key && (e = "" + a.key); void 0 !== a.ref && (h = a.ref); for (b in a) m$1.call(a, b) && !p.hasOwnProperty(b) && (d[b] = a[b]); if (c && c.defaultProps) for (b in a = c.defaultProps, a) void 0 === d[b] && (d[b] = a[b]); return { $$typeof: k, type: c, key: e, ref: h, props: d, _owner: n.current }; } reactJsxRuntime_production_min.Fragment = l; reactJsxRuntime_production_min.jsx = q; reactJsxRuntime_production_min.jsxs = q; { jsxRuntime.exports = reactJsxRuntime_production_min; } var jsxRuntimeExports = jsxRuntime.exports; var client = {}; var m = require$$0$1; { client.createRoot = m.createRoot; client.hydrateRoot = m.hydrateRoot; } var main = { exports: {} }; (function(module) { module.exports = /******/ function(modules) { var installedModules = {}; function __webpack_require__(moduleId) { if (installedModules[moduleId]) return installedModules[moduleId].exports; var module2 = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; modules[moduleId].call(module2.exports, module2, module2.exports, __webpack_require__); module2.loaded = true; return module2.exports; } __webpack_require__.m = modules; __webpack_require__.c = installedModules; __webpack_require__.p = ""; return __webpack_require__(0); }([ /* 0 */ /***/ function(module2, exports, __webpack_require__) { module2.exports = __webpack_require__(1); }, /* 1 */ /***/ function(module2, exports, __webpack_require__) { Object.defineProperty(exports, "__esModule", { value: true }); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } var _Highlighter = __webpack_require__(2); var _Highlighter2 = _interopRequireDefault(_Highlighter); exports["default"] = _Highlighter2["default"]; module2.exports = exports["default"]; }, /* 2 */ /***/ function(module2, exports, __webpack_require__) { Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports["default"] = Highlighter2; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } var _highlightWordsCore = __webpack_require__(3); var _propTypes = __webpack_require__(4); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = __webpack_require__(14); var _memoizeOne = __webpack_require__(15); var _memoizeOne2 = _interopRequireDefault(_memoizeOne); Highlighter2.propTypes = { activeClassName: _propTypes2["default"].string, activeIndex: _propTypes2["default"].number, activeStyle: _propTypes2["default"].object, autoEscape: _propTypes2["default"].bool, className: _propTypes2["default"].string, findChunks: _propTypes2["default"].func, highlightClassName: _propTypes2["default"].oneOfType([_propTypes2["default"].object, _propTypes2["default"].string]), highlightStyle: _propTypes2["default"].object, highlightTag: _propTypes2["default"].oneOfType([_propTypes2["default"].node, _propTypes2["default"].func, _propTypes2["default"].string]), sanitize: _propTypes2["default"].func, searchWords: _propTypes2["default"].arrayOf(_propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].instanceOf(RegExp)])).isRequired, textToHighlight: _propTypes2["default"].string.isRequired, unhighlightTag: _propTypes2["default"].oneOfType([_propTypes2["default"].node, _propTypes2["default"].func, _propTypes2["default"].string]), unhighlightClassName: _propTypes2["default"].string, unhighlightStyle: _propTypes2["default"].object }; function Highlighter2(_ref) { var _ref$activeClassName = _ref.activeClassName; var activeClassName = _ref$activeClassName === void 0 ? "" : _ref$activeClassName; var _ref$activeIndex = _ref.activeIndex; var activeIndex = _ref$activeIndex === void 0 ? -1 : _ref$activeIndex; var activeStyle = _ref.activeStyle; var autoEscape = _ref.autoEscape; var _ref$caseSensitive = _ref.caseSensitive; var caseSensitive = _ref$caseSensitive === void 0 ? false : _ref$caseSensitive; var className = _ref.className; var findChunks = _ref.findChunks; var _ref$highlightClassName = _ref.highlightClassName; var highlightClassName = _ref$highlightClassName === void 0 ? "" : _ref$highlightClassName; var _ref$highlightStyle = _ref.highlightStyle; var highlightStyle = _ref$highlightStyle === void 0 ? {} : _ref$highlightStyle; var _ref$highlightTag = _ref.highlightTag; var highlightTag = _ref$highlightTag === void 0 ? "mark" : _ref$highlightTag; var sanitize = _ref.sanitize; var searchWords = _ref.searchWords; var textToHighlight = _ref.textToHighlight; var _ref$unhighlightTag = _ref.unhighlightTag; var unhighlightTag = _ref$unhighlightTag === void 0 ? "span" : _ref$unhighlightTag; var _ref$unhighlightClassName = _ref.unhighlightClassName; var unhighlightClassName = _ref$unhighlightClassName === void 0 ? "" : _ref$unhighlightClassName; var unhighlightStyle = _ref.unhighlightStyle; var rest = _objectWithoutProperties(_ref, ["activeClassName", "activeIndex", "activeStyle", "autoEscape", "caseSensitive", "className", "findChunks", "highlightClassName", "highlightStyle", "highlightTag", "sanitize", "searchWords", "textToHighlight", "unhighlightTag", "unhighlightClassName", "unhighlightStyle"]); var chunks = (0, _highlightWordsCore.findAll)({ autoEscape, caseSensitive, findChunks, sanitize, searchWords, textToHighlight }); var HighlightTag = highlightTag; var highlightIndex = -1; var highlightClassNames = ""; var highlightStyles = void 0; var lowercaseProps = function lowercaseProps2(object) { var mapped = {}; for (var key in object) { mapped[key.toLowerCase()] = object[key]; } return mapped; }; var memoizedLowercaseProps = (0, _memoizeOne2["default"])(lowercaseProps); return (0, _react.createElement)("span", _extends({ className }, rest, { children: chunks.map(function(chunk, index) { var text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); if (chunk.highlight) { highlightIndex++; var highlightClass = void 0; if (typeof highlightClassName === "object") { if (!caseSensitive) { highlightClassName = memoizedLowercaseProps(highlightClassName); highlightClass = highlightClassName[text.toLowerCase()]; } else { highlightClass = highlightClassName[text]; } } else { highlightClass = highlightClassName; } var isActive = highlightIndex === +activeIndex; highlightClassNames = highlightClass + " " + (isActive ? activeClassName : ""); highlightStyles = isActive === true && activeStyle != null ? Object.assign({}, highlightStyle, activeStyle) : highlightStyle; var props = { children: text, className: highlightClassNames, key: index, style: highlightStyles }; if (typeof HighlightTag !== "string") { props.highlightIndex = highlightIndex; } return (0, _react.createElement)(HighlightTag, props); } else { return (0, _react.createElement)(unhighlightTag, { children: text, className: unhighlightClassName, key: index, style: unhighlightStyle }); } }) })); } module2.exports = exports["default"]; }, /* 3 */ /***/ function(module2, exports) { module2.exports = /******/ function(modules) { var installedModules = {}; function __webpack_require__(moduleId) { if (installedModules[moduleId]) return installedModules[moduleId].exports; var module3 = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; modules[moduleId].call(module3.exports, module3, module3.exports, __webpack_require__); module3.loaded = true; return module3.exports; } __webpack_require__.m = modules; __webpack_require__.c = installedModules; __webpack_require__.p = ""; return __webpack_require__(0); }([ /* 0 */ /***/ function(module3, exports2, __webpack_require__) { module3.exports = __webpack_require__(1); }, /* 1 */ /***/ function(module3, exports2, __webpack_require__) { Object.defineProperty(exports2, "__esModule", { value: true }); var _utils = __webpack_require__(2); Object.defineProperty(exports2, "combineChunks", { enumerable: true, get: function get() { return _utils.combineChunks; } }); Object.defineProperty(exports2, "fillInChunks", { enumerable: true, get: function get() { return _utils.fillInChunks; } }); Object.defineProperty(exports2, "findAll", { enumerable: true, get: function get() { return _utils.findAll; } }); Object.defineProperty(exports2, "findChunks", { enumerable: true, get: function get() { return _utils.findChunks; } }); }, /* 2 */ /***/ function(module3, exports2) { Object.defineProperty(exports2, "__esModule", { value: true }); exports2.findAll = function findAll(_ref) { var autoEscape = _ref.autoEscape, _ref$caseSensitive = _ref.caseSensitive, caseSensitive = _ref$caseSensitive === void 0 ? false : _ref$caseSensitive, _ref$findChunks = _ref.findChunks, findChunks = _ref$findChunks === void 0 ? defaultFindChunks : _ref$findChunks, sanitize = _ref.sanitize, searchWords = _ref.searchWords, textToHighlight = _ref.textToHighlight; return fillInChunks({ chunksToHighlight: combineChunks({ chunks: findChunks({ autoEscape, caseSensitive, sanitize, searchWords, textToHighlight }) }), totalLength: textToHighlight ? textToHighlight.length : 0 }); }; var combineChunks = exports2.combineChunks = function combineChunks2(_ref2) { var chunks = _ref2.chunks; chunks = chunks.sort(function(first, second) { return first.start - second.start; }).reduce(function(processedChunks, nextChunk) { if (processedChunks.length === 0) { return [nextChunk]; } else { var prevChunk = processedChunks.pop(); if (nextChunk.start <= prevChunk.end) { var endIndex = Math.max(prevChunk.end, nextChunk.end); processedChunks.push({ start: prevChunk.start, end: endIndex }); } else { processedChunks.push(prevChunk, nextChunk); } return processedChunks; } }, []); return chunks; }; var defaultFindChunks = function defaultFindChunks2(_ref3) { var autoEscape = _ref3.autoEscape, caseSensitive = _ref3.caseSensitive, _ref3$sanitize = _ref3.sanitize, sanitize = _ref3$sanitize === void 0 ? identity : _ref3$sanitize, searchWords = _ref3.searchWords, textToHighlight = _ref3.textToHighlight; textToHighlight = sanitize(textToHighlight); return searchWords.filter(function(searchWord) { return searchWord; }).reduce(function(chunks, searchWord) { searchWord = sanitize(searchWord); if (autoEscape) { searchWord = escapeRegExpFn(searchWord); } var regex = new RegExp(searchWord, caseSensitive ? "g" : "gi"); var match = void 0; while (match = regex.exec(textToHighlight)) { var start = match.index; var end = regex.lastIndex; if (end > start) { chunks.push({ start, end }); } if (match.index == regex.lastIndex) { regex.lastIndex++; } } return chunks; }, []); }; exports2.findChunks = defaultFindChunks; var fillInChunks = exports2.fillInChunks = function fillInChunks2(_ref4) { var chunksToHighlight = _ref4.chunksToHighlight, totalLength = _ref4.totalLength; var allChunks = []; var append = function append2(start, end, highlight) { if (end - start > 0) { allChunks.push({ start, end, highlight }); } }; if (chunksToHighlight.length === 0) { append(0, totalLength, false); } else { var lastIndex = 0; chunksToHighlight.forEach(function(chunk) { append(lastIndex, chunk.start, false); append(chunk.start, chunk.end, true); lastIndex = chunk.end; }); append(lastIndex, totalLength, false); } return allChunks; }; function identity(value) { return value; } function escapeRegExpFn(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } } /******/ ]); }, /* 4 */ /***/ function(module2, exports, __webpack_require__) { (function(process) { { module2.exports = __webpack_require__(13)(); } }).call(exports, __webpack_require__(5)); }, /* 5 */ /***/ function(module2, exports) { var process = module2.exports = {}; var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error("setTimeout has not been defined"); } function defaultClearTimeout() { throw new Error("clearTimeout has not been defined"); } (function() { try { if (typeof setTimeout === "function") { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === "function") { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } })(); function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { return setTimeout(fun, 0); } if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { return cachedSetTimeout(fun, 0); } catch (e) { try { return cachedSetTimeout.call(null, fun, 0); } catch (e2) { return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { return clearTimeout(marker); } if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { return cachedClearTimeout(marker); } catch (e) { try { return cachedClearTimeout.call(null, marker); } catch (e2) { return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while (len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function(fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function() { this.fun.apply(null, this.array); }; process.title = "browser"; process.browser = true; process.env = {}; process.argv = []; process.version = ""; process.versions = {}; function noop() { } process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; process.listeners = function(name2) { return []; }; process.binding = function(name2) { throw new Error("process.binding is not supported"); }; process.cwd = function() { return "/"; }; process.chdir = function(dir) { throw new Error("process.chdir is not supported"); }; process.umask = function() { return 0; }; }, /* 6 */ /***/ function(module2, exports, __webpack_require__) { (function(process) { var emptyFunction = __webpack_require__(7); var invariant = __webpack_require__(8); var warning = __webpack_require__(9); var assign = __webpack_require__(10); var ReactPropTypesSecret = __webpack_require__(11); var checkPropTypes = __webpack_require__(12); module2.exports = function(isValidElement, throwOnDirectAccess) { var ITERATOR_SYMBOL = typeof Symbol === "function" && Symbol.iterator; var FAUX_ITERATOR_SYMBOL = "@@iterator"; function getIteratorFn(maybeIterable) { var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]); if (typeof iteratorFn === "function") { return iteratorFn; } } var ANONYMOUS = "<<anonymous>>"; var ReactPropTypes = { array: createPrimitiveTypeChecker("array"), bool: createPrimitiveTypeChecker("boolean"), func: createPrimitiveTypeChecker("function"), number: createPrimitiveTypeChecker("number"), object: createPrimitiveTypeChecker("object"), string: createPrimitiveTypeChecker("string"), symbol: createPrimitiveTypeChecker("symbol"), any: createAnyTypeChecker(), arrayOf: createArrayOfTypeChecker, element: createElementTypeChecker(), instanceOf: createInstanceTypeChecker, node: createNodeChecker(), objectOf: createObjectOfTypeChecker, oneOf: createEnumTypeChecker, oneOfType: createUnionTypeChecker, shape: createShapeTypeChecker, exact: createStrictShapeTypeChecker }; function is(x, y) { if (x === y) { return x !== 0 || 1 / x === 1 / y; } else { return x !== x && y !== y; } } function PropTypeError(message) { this.message = message; this.stack = ""; } PropTypeError.prototype = Error.prototype; function createChainableTypeChecker(validate) { function checkType(isRequired, props, propName, componentName, location, propFullName, secret) { componentName = componentName || ANONYMOUS; propFullName = propFullName || propName; if (secret !== ReactPropTypesSecret) { if (throwOnDirectAccess) { invariant( false, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use `PropTypes.checkPropTypes()` to call them. Read more at http://fb.me/use-check-prop-types" ); } } if (props[propName] == null) { if (isRequired) { if (props[propName] === null) { return new PropTypeError("The " + location + " `" + propFullName + "` is marked as required " + ("in `" + componentName + "`, but its value is `null`.")); } return new PropTypeError("The " + location + " `" + propFullName + "` is marked as required in " + ("`" + componentName + "`, but its value is `undefined`.")); } return null; } else { return validate(props, propName, componentName, location, propFullName); } } var chainedCheckType = checkType.bind(null, false); chainedCheckType.isRequired = checkType.bind(null, true); return chainedCheckType; } function createPrimitiveTypeChecker(expectedType) { function validate(props, propName, componentName, location, propFullName, secret) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== expectedType) { var preciseType = getPreciseType(propValue); return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + preciseType + "` supplied to `" + componentName + "`, expected ") + ("`" + expectedType + "`.")); } return null; } return createChainableTypeChecker(validate); } function createAnyTypeChecker() { return createChainableTypeChecker(emptyFunction.thatReturnsNull); } function createArrayOfTypeChecker(typeChecker) { function validate(props, propName, componentName, location, propFullName) { if (typeof typeChecker !== "function") { return new PropTypeError("Property `" + propFullName + "` of component `" + componentName + "` has invalid PropType notation inside arrayOf."); } var propValue = props[propName]; if (!Array.isArray(propValue)) { var propType = getPropType(propValue); return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + propType + "` supplied to `" + componentName + "`, expected an array.")); } for (var i = 0; i < propValue.length; i++) { var error = typeChecker(propValue, i, componentName, location, propFullName + "[" + i + "]", ReactPropTypesSecret); if (error instanceof Error) { return error; } } return null; } return createChainableTypeChecker(validate); } function createElementTypeChecker() { function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; if (!isValidElement(propValue)) { var propType = getPropType(propValue); return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + propType + "` supplied to `" + componentName + "`, expected a single ReactElement.")); } return null; } return createChainableTypeChecker(validate); } function createInstanceTypeChecker(expectedClass) { function validate(props, propName, componentName, location, propFullName) { if (!(props[propName] instanceof expectedClass)) { var expectedClassName = expectedClass.name || ANONYMOUS; var actualClassName = getClassName(props[propName]); return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + actualClassName + "` supplied to `" + componentName + "`, expected ") + ("instance of `" + expectedClassName + "`.")); } return null; } return createChainableTypeChecker(validate); } function createEnumTypeChecker(expectedValues) { if (!Array.isArray(expectedValues)) { return emptyFunction.thatReturnsNull; } function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; for (var i = 0; i < expectedValues.length; i++) { if (is(propValue, expectedValues[i])) { return null; } } var valuesString = JSON.stringify(expectedValues); return new PropTypeError("Invalid " + location + " `" + propFullName + "` of value `" + propValue + "` " + ("supplied to `" + componentName + "`, expected one of " + valuesString + ".")); } return createChainableTypeChecker(validate); } function createObjectOfTypeChecker(typeChecker) { function validate(props, propName, componentName, location, propFullName) { if (typeof typeChecker !== "function") { return new PropTypeError("Property `" + propFullName + "` of component `" + componentName + "` has invalid PropType notation inside objectOf."); } var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== "object") { return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type " + ("`" + propType + "` supplied to `" + componentName + "`, expected an object.")); } for (var key in propValue) { if (propValue.hasOwnProperty(key)) { var error = typeChecker(propValue, key, componentName, location, propFullName + "." + key, ReactPropTypesSecret); if (error instanceof Error) { return error; } } } return null; } return createChainableTypeChecker(validate); } function createUnionTypeChecker(arrayOfTypeCheckers) { if (!Array.isArray(arrayOfTypeCheckers)) { return emptyFunction.thatReturnsNull; } for (var i = 0; i < arrayOfTypeCheckers.length; i++) { var checker = arrayOfTypeCheckers[i]; if (typeof checker !== "function") { warning( false, "Invalid argument supplied to oneOfType. Expected an array of check functions, but received %s at index %s.", getPostfixForTypeWarning(checker), i ); return emptyFunction.thatReturnsNull; } } function validate(props, propName, componentName, location, propFullName) { for (var i2 = 0; i2 < arrayOfTypeCheckers.length; i2++) { var checker2 = arrayOfTypeCheckers[i2]; if (checker2(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) { return null; } } return new PropTypeError("Invalid " + location + " `" + propFullName + "` supplied to " + ("`" + componentName + "`.")); } return createChainableTypeChecker(validate); } function createNodeChecker() { function validate(props, propName, componentName, location, propFullName) { if (!isNode(props[propName])) { return new PropTypeError("Invalid " + location + " `" + propFullName + "` supplied to " + ("`" + componentName + "`, expected a ReactNode.")); } return null; } return createChainableTypeChecker(validate); } function createShapeTypeChecker(shapeTypes) { function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== "object") { return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type `" + propType + "` " + ("supplied to `" + componentName + "`, expected `object`.")); } for (var key in shapeTypes) { var checker = shapeTypes[key]; if (!checker) { continue; } var error = checker(propValue, key, componentName, location, propFullName + "." + key, ReactPropTypesSecret); if (error) { return error; } } return null; } return createChainableTypeChecker(validate); } function createStrictShapeTypeChecker(shapeTypes) { function validate(props, propName, componentName, location, propFullName) { var propValue = props[propName]; var propType = getPropType(propValue); if (propType !== "object") { return new PropTypeError("Invalid " + location + " `" + propFullName + "` of type `" + propType + "` " + ("supplied to `" + componentName + "`, expected `object`.")); } var allKeys = assign({}, props[propName], shapeTypes); for (var key in allKeys) { var checker = shapeTypes[key]; if (!checker) { return new PropTypeError( "Invalid " + location + " `" + propFullName + "` key `" + key + "` supplied to `" + componentName + "`.\nBad object: " + JSON.stringify(props[propName], null, " ") + "\nValid keys: " + JSON.stringify(Object.keys(shapeTypes), null, " ") ); } var error = checker(propValue, key, componentName, location, propFullName + "." + key, ReactPropTypesSecret); if (error) { return error; } } return null; } return createChainableTypeChecker(validate); } function isNode(propValue) { switch (typeof propValue) { case "number": case "string": case "undefined": return true; case "boolean": return !propValue; case "object": if (Array.isArray(propValue)) { return propValue.every(isNode); } if (propValue === null || isValidElement(propValue)) { return true; } var iteratorFn = getIteratorFn(propValue); if (iteratorFn) { var iterator = iteratorFn.call(propValue); var step; if (iteratorFn !== propValue.entries) { while (!(step = iterator.next()).done) { if (!isNode(step.value)) { return false; } } } else { while (!(step = iterator.next()).done) { var entry = step.value; if (entry) { if (!isNode(entry[1])) { return false; } } } } } else { return false; } return true; default: return false; } } function isSymbol(propType, propValue) { if (propType === "symbol") { return true; } if (propValue["@@toStringTag"] === "Symbol") { return true; } if (typeof Symbol === "function" && propValue instanceof Symbol) { return true; } return false; } function getPropType(propValue) { var propType = typeof propValue; if (Array.isArray(propValue)) { return "array"; } if (propValue instanceof RegExp) { return "object"; } if (isSymbol(propType, propValue)) { return "symbol"; } return propType; } function getPreciseType(propValue) { if (typeof propValue === "undefined" || propValue === null) { return "" + propValue; } var propType = getPropType(propValue); if (propType === "object") { if (propValue instanceof Date) { return "date"; } else if (propValue instanceof RegExp) { return "regexp"; } } return propType; } function getPostfixForTypeWarning(value) { var type = getPreciseType(value); switch (type) { case "array": case "object": return "an " + type; case "boolean": case "date": case "regexp": return "a " + type; default: return type; } } function getClassName(propValue) { if (!propValue.constructor || !propValue.constructor.name) { return ANONYMOUS; } return propValue.constructor.name; } ReactPropTypes.checkPropTypes = checkPropTypes; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes; }; }).call(exports, __webpack_require__(5)); }, /* 7 */ /***/ function(module2, exports) { function makeEmptyFunction(arg) { return function() { return arg; }; } var emptyFunction = function emptyFunction2() { }; emptyFunction.thatReturns = makeEmptyFunction; emptyFunction.thatReturnsFalse = makeEmptyFunction(false); emptyFunction.thatReturnsTrue = makeEmptyFunction(true); emptyFunction.thatReturnsNull = makeEmptyFunction(null); emptyFunction.thatReturnsThis = function() { return this; }; emptyFunction.thatReturnsArgument = function(arg) { return arg; }; module2.exports = emptyFunction; }, /* 8 */ /***/ function(module2, exports, __webpack_require__) { (function(process) { function invariant(condition, format, a, b, c, d, e, f2) { if (!condition) { var error; if (format === void 0) { error = new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings."); } else { var args = [a, b, c, d, e, f2]; var argIndex = 0; error = new Error(format.replace(/%s/g, function() { return args[argIndex++]; })); error.name = "Invariant Violation"; } error.framesToPop = 1; throw error; } } module2.exports = invariant; }).call(exports, __webpack_require__(5)); }, /* 9 */ /***/ function(module2, exports, __webpack_require__) { (function(process) { var emptyFunction = __webpack_require__(7); var warning = emptyFunction; module2.exports = warning; }).call(exports, __webpack_require__(5)); }, /* 10 */ /***/ function(module2, exports) { var getOwnPropertySymbols = Object.getOwnPropertySymbols; var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; function toObject(val) { if (val === null || val === void 0) { throw new TypeError("Object.assign cannot be called with null or undefined"); } return Object(val); } function shouldUseNative() { try { if (!Object.assign) { return false; } var test1 = new String("abc"); test1[5] = "de"; if (Object.getOwnPropertyNames(test1)[0] === "5") { return false; } var test2 = {}; for (var i = 0; i < 10; i++) { test2["_" + String.fromCharCode(i)] = i; } var order2 = Object.getOwnPropertyNames(test2).map(function(n2) { return test2[n2]; }); if (order2.join("") !== "0123456789") { return false; } var test3 = {}; "abcdefghijklmnopqrst".split("").forEach(function(letter) { test3[letter] = letter; }); if (Object.keys(Object.assign({}, test3)).join("") !== "abcdefghijklmnopqrst") { return false; } return true; } catch (err) { return false; } } module2.exports = shouldUseNative() ? Object.assign : function(target, source) { var from; var to = toObject(target); var symbols; for (var s = 1; s < arguments.length; s++) { from = Object(arguments[s]); for (var key in from) { if (hasOwnProperty.call(from, key)) { to[key] = from[key]; } } if (getOwnPropertySymbols) { symbols = getOwnPropertySymbols(from); for (var i = 0; i < symbols.length; i++) { if (propIsEnumerable.call(from, symbols[i])) { to[symbols[i]] = from[symbols[i]]; } } } } return to; }; }, /* 11 */ /***/ function(module2, exports) { var ReactPropTypesSecret = "SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"; module2.exports = ReactPropTypesSecret; }, /* 12 */ /***/ function(module2, exports, __webpack_require__) { (function(process) { function checkPropTypes(typeSpecs, values, location, componentName, getStack) { } module2.exports = checkPropTypes; }).call(exports, __webpack_require__(5)); }, /* 13 */ /***/ function(module2, exports, __webpack_require__) { var emptyFunction = __webpack_require__(7); var invariant = __webpack_require__(8); var ReactPropTypesSecret = __webpack_require__(11); module2.exports = function() { function shim(props, propName, componentName, location, propFullName, secret) { if (secret === ReactPropTypesSecret) { return; } invariant( false, "Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types" ); } shim.isRequired = shim; function getShim() { return shim; } var ReactPropTypes = { array: shim, bool: shim, func: shim, number: shim, object: shim, string: shim, symbol: shim, any: shim, arrayOf: getShim, element: shim, instanceOf: getShim, node: shim, objectOf: getShim, oneOf: getShim, oneOfType: getShim, shape: getShim, exact: getShim }; ReactPropTypes.checkPropTypes = emptyFunction; ReactPropTypes.PropTypes = ReactPropTypes; return ReactPropTypes; }; }, /* 14 */ /***/ function(module2, exports) { module2.exports = require$$0; }, /* 15 */ /***/ function(module2, exports) { var simpleIsEqual = function simpleIsEqual2(a, b) { return a === b; }; function index(r###ltFn) { var isEqual = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : simpleIsEqual; var lastThis = void 0; var lastArgs = []; var lastR###lt = void 0; var calledOnce = false; var isNewArgEqualToLast = function isNewArgEqualToLast2(newArg, index2) { return isEqual(newArg, lastArgs[index2]); }; var r###lt = function r###lt2() { for (var _len = arguments.length, newArgs = Array(_len), _key = 0; _key < _len; _key++) { newArgs[_key] = arguments[_key]; } if (calledOnce && lastThis === this && newArgs.length === lastArgs.length && newArgs.every(isNewArgEqualToLast)) { return lastR###lt; } calledOnce = true; lastThis = this; lastArgs = newArgs; lastR###lt = r###ltFn.apply(this, newArgs); return lastR###lt; }; return r###lt; } module2.exports = index; } /******/ ]); })(main); var mainExports = main.exports; const Highlighter = /* @__PURE__ */ getDefaultExportFromCjs(mainExports); var CommentType = /* @__PURE__ */ ((CommentType2) => { CommentType2[CommentType2["VIDEO"] = 1] = "VIDEO"; CommentType2[CommentType2["TOPIC"] = 2] = "TOPIC"; CommentType2[CommentType2["ACTIVITY"] = 4] = "ACTIVITY"; CommentType2[CommentType2["SHORT_VIDEO"] = 5] = "SHORT_VIDEO"; CommentType2[CommentType2["BAN_INFO"] = 6] = "BAN_INFO"; CommentType2[CommentType2["NOTICE"] = 7] = "NOTICE"; CommentType2[CommentType2["LIVE_ACTIVITY"] = 8] = "LIVE_ACTIVITY"; CommentType2[CommentType2["ACTIVITY_ARTICLE"] = 9] = "ACTIVITY_ARTICLE"; CommentType2[CommentType2["LIVE_NOTICE"] = 10] = "LIVE_NOTICE"; CommentType2[CommentType2["ALBUM"] = 11] = "ALBUM"; CommentType2[CommentType2["COLUMN"] = 12] = "COLUMN"; CommentType2[CommentType2["TICKET"] = 13] = "TICKET"; CommentType2[CommentType2["AUDIO"] = 14] = "AUDIO"; CommentType2[CommentType2["JURY"] = 15] = "JURY"; CommentType2[CommentType2["REVIEW"] = 16] = "REVIEW"; CommentType2[CommentType2["DYNAMIC"] = 17] = "DYNAMIC"; CommentType2[CommentType2["PLAYLIST"] = 18] = "PLAYLIST"; CommentType2[CommentType2["MUSIC_PLAYLIST"] = 19] = "MUSIC_PLAYLIST"; CommentType2[CommentType2["COMIC_1"] = 20] = "COMIC_1"; CommentType2[CommentType2["COMIC_2"] = 21] = "COMIC_2"; CommentType2[CommentType2["COMIC_3"] = 22] = "COMIC_3"; CommentType2[CommentType2["COURSE"] = 33] = "COURSE"; return CommentType2; })(CommentType || {}); var CommentSort = /* @__PURE__ */ ((CommentSort2) => { CommentSort2[CommentSort2["TIME"] = 0] = "TIME"; CommentSort2[CommentSort2["LIKES"] = 1] = "LIKES"; CommentSort2[CommentSort2["REPLIES"] = 2] = "REPLIES"; return CommentSort2; })(CommentSort || {}); const name = "userscript-bilibili-comment-search"; const version = "0.2.0"; function assertEl(el) { if (!el) { throw new Error("Element not found"); } return el; } function debug(message) { console.log(`[${name}] ${message}`); } function extractVideoId(url) { const match = url.match(/\/video\/(BV\w+)\//); if (!match) { throw new Error(`Failed to extract video id from url: ${url}`); } return match[1]; } function formatDateTime(ts) { const date = new Date(ts * 1e3); return date.toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false }); } const PAGE_LIMIT = 20; const replies = []; async function fetchComments(videoId) { if (replies.length > 0) { return replies; } const pageSize = 20; let page = 1; while (true) { const params = new URLSearchParams({ type: CommentType.VIDEO.toString(), oid: videoId, sort: CommentSort.TIME.toString(), pn: page.toString(), ps: pageSize.toString() }); debug(`fetch comments: page ${page}`); const response = await fetch( `https://api.bilibili.com/x/v2/reply?${params}`, { credentials: "include" } ); const data = await response.json(); if (data.code !== 0) { throw new Error(`Failed to fetch comments: ${data.message}`); } if (!data.data) { throw new Error(`Failed to fetch comments: ${data.message}`); } replies.push(...data.data.replies ?? []); if (page * pageSize >= Math.min(PAGE_LIMIT * pageSize, data.data.page.count)) { break; } page++; } return replies; } let keyword = ""; function App() { const dialogRef = require$$0.useRef(null); const inputRef = require$$0.useRef(null); const [comments, setComments] = require$$0.useState(); const promiseRef = require$$0.useRef(null); return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs( "dialog", { ref: dialogRef, onClick: (e) => { const rect = e.currentTarget.getBoundingClientRect(); if (e.clientY < rect.top || e.clientY > rect.bottom || e.clientX < rect.left || e.clientX > rect.right) { e.currentTarget.close(); } }, children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "header", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("h1", { children: [ "Bilibili Comment Search ", "", /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [ "v", version ] }) ] }), /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => { var _a; return (_a = dialogRef.current) == null ? void 0 : _a.close(); }, children: "X" }) ] }), /* @__PURE__ */ jsxRuntimeExports.jsx( "input", { ref: inputRef, placeholder: "搜索评论", onKeyDown: (e) => { if (e.key === "Enter" && promiseRef.current) { e.preventDefault(); keyword = e.currentTarget.value; promiseRef.current.then((allComments) => { const comments2 = searchComments(allComments); setComments(comments2); }).catch((e2) => { console.error(e2); }); } } } ), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "note", children: [ "Note: 由于性能和 Rate Limit 的原因,目前仅会加载 ", PAGE_LIMIT, " ", "页评论,即 ", PAGE_LIMIT, " * 20 条评论,及其至多 3 条子评论。" ] }), /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "comment-tree", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CommentTree, { comments }) }) ] } ), /* @__PURE__ */ jsxRuntimeExports.jsx( "button", { onClick: () => { var _a, _b; (_a = dialogRef.current) == null ? void 0 : _a.showModal(); (_b = inputRef.current) == null ? void 0 : _b.focus(); const videoId = extractVideoId(window.location.href); promiseRef.current = fetchComments(videoId); }, children: "搜索评论" } ) ] }); } const CommentTree = ({ comments, sub = false }) => { if (!comments) return null; return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { children: comments.sort((c1, c2) => c1.ctime - c2.ctime).map((comment) => /* @__PURE__ */ jsxRuntimeExports.jsxs( "li", { className: "comment-item", style: { marginTop: sub ? "10px" : "20px" }, children: [ /* @__PURE__ */ jsxRuntimeExports.jsx( "img", { src: comment.member.avatar, className: "comment-item-avatar", style: { width: sub ? "28px" : "40px", height: sub ? "28px" : "40px" } } ), /* @__PURE__ */ jsxRuntimeExports.jsxs( "div", { className: "comment-item-content", style: { ...!sub && { display: "flex", flexDirection: "column" } }, children: [ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "comment-item-username", children: comment.member.uname }), /* @__PURE__ */ jsxRuntimeExports.jsx( Highlighter, { className: "comment-item-message", highlightClassName: "comment-item-highlight", searchWords: [keyword], autoEscape: true, textToHighlight: comment.content.message } ), /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "comment-item-time", children: formatDateTime(comment.ctime) }), /* @__PURE__ */ jsxRuntimeExports.jsx(CommentTree, { comments: comment.replies, sub: true }) ] } ) ] }, comment.rpid )) }); }; function searchComments(allComments) { return allComments.filter((comment) => { var _a; return comment.content.message.includes(keyword) || ((_a = comment.replies) == null ? void 0 : _a.some((reply) => reply.content.message.includes(keyword))); }); } function run() { debug("run"); const id = "comment-search-root"; let root = document.querySelector(`#${id}`); if (root) { debug("root exists"); return; } const container = assertEl(document.querySelector("#commentapp")); root = document.createElement("div"); root.id = id; container.prepend(root); debug("render"); client.createRoot(root).render( /* @__PURE__ */ jsxRuntimeExports.jsx(require$$0.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {}) }) ); } window.addEventListener("load", () => { const timer = setInterval(() => { try { run(); clearInterval(timer); } catch (error) { } }, 500); }); })(React, ReactDOM);