github-issues-wiki

github issues viewer

  1. // ==UserScript==
  2. // @name github-issues-wiki
  3. // @namespace npm/vite-plugin-monkey
  4. // @version 0.0.1
  5. // @description github issues viewer
  6. // @author monkey
  7. // @icon https://vitejs.dev/logo.svg
  8. // @match https://github.com/*
  9. // @require https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (t=>{const e=document.createElement("style");e.dataset.source="vite-plugin-monkey",e.textContent=t,document.head.append(e)})(" :root.issue-active{padding-left:250px}#app{width:250px;height:100%;text-align:center;position:fixed;left:0;top:0;z-index:999;display:none}#app.active{display:block}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{border-radius:3px;background:rgba(0,0,0,.06);-webkit-box-shadow:inset 0 0 5px rgba(0,0,0,.08)}::-webkit-scrollbar-thumb{border-radius:3px;background:rgba(0,0,0,.12);-webkit-box-shadow:inset 0 0 10px rgba(0,0,0,.2)}.item-inner[data-v-8ef0fbfc]{text-align:left;border-top:1px solid gray;padding:10px 0}.item-inner .head[data-v-8ef0fbfc]{font-weight:500;display:flex;flex-direction:row}.item-inner .index[data-v-8ef0fbfc]{margin-right:3px}.item-inner .name[data-v-8ef0fbfc]{margin-left:5px;word-break:break-all;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}.item-inner .desc[data-v-8ef0fbfc]{padding-top:.5em;text-align:justify}.item-inner[data-v-8ef0fbfc]:hover{background-color:#dcffff;cursor:default}.list-infinite[data-v-8e8d3fd2]{width:100%;height:100%;border:2px solid;border-radius:3px;overflow-y:scroll;max-height:100%;border-color:#696969;position:relative;background-color:#fff;padding-left:5px;padding-right:5px}.list-infinite .list-item-infinite[data-v-8e8d3fd2]{display:flex;align-items:center;padding:1em;border-bottom:1px solid;border-color:#d3d3d3}.list-infinite .loader[data-v-8e8d3fd2]{margin-top:5px;letter-spacing:3px} ");
  14.  
  15. (function (vue) {
  16. 'use strict';
  17.  
  18. function ownKeys(object, enumerableOnly) {
  19. var keys = Object.keys(object);
  20. if (Object.getOwnPropertySymbols) {
  21. var symbols = Object.getOwnPropertySymbols(object);
  22. if (enumerableOnly) {
  23. symbols = symbols.filter(function(sym) {
  24. return Object.getOwnPropertyDescriptor(object, sym).enumerable;
  25. });
  26. }
  27. keys.push.apply(keys, symbols);
  28. }
  29. return keys;
  30. }
  31. function _objectSpread2(target) {
  32. for (var i = 1; i < arguments.length; i++) {
  33. var source = arguments[i] != null ? arguments[i] : {};
  34. if (i % 2) {
  35. ownKeys(Object(source), true).forEach(function(key) {
  36. _defineProperty(target, key, source[key]);
  37. });
  38. } else if (Object.getOwnPropertyDescriptors) {
  39. Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
  40. } else {
  41. ownKeys(Object(source)).forEach(function(key) {
  42. Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
  43. });
  44. }
  45. }
  46. return target;
  47. }
  48. function _classCallCheck(instance, Constructor) {
  49. if (!(instance instanceof Constructor)) {
  50. throw new TypeError("Cannot call a class as a function");
  51. }
  52. }
  53. function _defineProperties(target, props) {
  54. for (var i = 0; i < props.length; i++) {
  55. var descriptor = props[i];
  56. descriptor.enumerable = descriptor.enumerable || false;
  57. descriptor.configurable = true;
  58. if ("value" in descriptor)
  59. descriptor.writable = true;
  60. Object.defineProperty(target, descriptor.key, descriptor);
  61. }
  62. }
  63. function _createClass(Constructor, protoProps, staticProps) {
  64. if (protoProps)
  65. _defineProperties(Constructor.prototype, protoProps);
  66. if (staticProps)
  67. _defineProperties(Constructor, staticProps);
  68. return Constructor;
  69. }
  70. function _defineProperty(obj, key, value) {
  71. if (key in obj) {
  72. Object.defineProperty(obj, key, {
  73. value,
  74. enumerable: true,
  75. configurable: true,
  76. writable: true
  77. });
  78. } else {
  79. obj[key] = value;
  80. }
  81. return obj;
  82. }
  83. function _toConsumableArray(arr) {
  84. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  85. }
  86. function _arrayWithoutHoles(arr) {
  87. if (Array.isArray(arr))
  88. return _arrayLikeToArray(arr);
  89. }
  90. function _iterableToArray(iter) {
  91. if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null)
  92. return Array.from(iter);
  93. }
  94. function _unsupportedIterableToArray(o, minLen) {
  95. if (!o)
  96. return;
  97. if (typeof o === "string")
  98. return _arrayLikeToArray(o, minLen);
  99. var n = Object.prototype.toString.call(o).slice(8, -1);
  100. if (n === "Object" && o.constructor)
  101. n = o.constructor.name;
  102. if (n === "Map" || n === "Set")
  103. return Array.from(o);
  104. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
  105. return _arrayLikeToArray(o, minLen);
  106. }
  107. function _arrayLikeToArray(arr, len) {
  108. if (len == null || len > arr.length)
  109. len = arr.length;
  110. for (var i = 0, arr2 = new Array(len); i < len; i++)
  111. arr2[i] = arr[i];
  112. return arr2;
  113. }
  114. function _nonIterableSpread() {
  115. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  116. }
  117. var DIRECTION_TYPE = {
  118. FRONT: "FRONT",
  119. // scroll up or left
  120. BEHIND: "BEHIND"
  121. // scroll down or right
  122. };
  123. var CALC_TYPE = {
  124. INIT: "INIT",
  125. FIXED: "FIXED",
  126. DYNAMIC: "DYNAMIC"
  127. };
  128. var LEADING_BUFFER = 2;
  129. var Virtual = /* @__PURE__ */ function() {
  130. function Virtual2(param, callUpdate) {
  131. _classCallCheck(this, Virtual2);
  132. this.init(param, callUpdate);
  133. }
  134. _createClass(Virtual2, [{
  135. key: "init",
  136. value: function init(param, callUpdate) {
  137. this.param = param;
  138. this.callUpdate = callUpdate;
  139. this.sizes = /* @__PURE__ */ new Map();
  140. this.firstRangeTotalSize = 0;
  141. this.firstRangeAverageSize = 0;
  142. this.lastCalcIndex = 0;
  143. this.fixedSizeValue = 0;
  144. this.calcType = CALC_TYPE.INIT;
  145. this.offset = 0;
  146. this.direction = "";
  147. this.range = /* @__PURE__ */ Object.create(null);
  148. if (param) {
  149. this.checkRange(0, param.keeps - 1);
  150. }
  151. }
  152. }, {
  153. key: "destroy",
  154. value: function destroy() {
  155. this.init(null, null);
  156. }
  157. // return current render range
  158. }, {
  159. key: "getRange",
  160. value: function getRange() {
  161. var range = /* @__PURE__ */ Object.create(null);
  162. range.start = this.range.start;
  163. range.end = this.range.end;
  164. range.padFront = this.range.padFront;
  165. range.padBehind = this.range.padBehind;
  166. return range;
  167. }
  168. }, {
  169. key: "isBehind",
  170. value: function isBehind() {
  171. return this.direction === DIRECTION_TYPE.BEHIND;
  172. }
  173. }, {
  174. key: "isFront",
  175. value: function isFront() {
  176. return this.direction === DIRECTION_TYPE.FRONT;
  177. }
  178. // return start index offset
  179. }, {
  180. key: "getOffset",
  181. value: function getOffset(start) {
  182. return (start < 1 ? 0 : this.getIndexOffset(start)) + this.param.slotHeaderSize;
  183. }
  184. }, {
  185. key: "updateParam",
  186. value: function updateParam(key, value) {
  187. var _this = this;
  188. if (this.param && key in this.param) {
  189. if (key === "uniqueIds") {
  190. this.sizes.forEach(function(v, key2) {
  191. if (!value.includes(key2)) {
  192. _this.sizes["delete"](key2);
  193. }
  194. });
  195. }
  196. this.param[key] = value;
  197. }
  198. }
  199. // save each size map by id
  200. }, {
  201. key: "saveSize",
  202. value: function saveSize(id, size) {
  203. this.sizes.set(id, size);
  204. if (this.calcType === CALC_TYPE.INIT) {
  205. this.fixedSizeValue = size;
  206. this.calcType = CALC_TYPE.FIXED;
  207. } else if (this.calcType === CALC_TYPE.FIXED && this.fixedSizeValue !== size) {
  208. this.calcType = CALC_TYPE.DYNAMIC;
  209. delete this.fixedSizeValue;
  210. }
  211. if (this.calcType !== CALC_TYPE.FIXED && typeof this.firstRangeTotalSize !== "undefined") {
  212. if (this.sizes.size < Math.min(this.param.keeps, this.param.uniqueIds.length)) {
  213. this.firstRangeTotalSize = _toConsumableArray(this.sizes.values()).reduce(function(acc, val) {
  214. return acc + val;
  215. }, 0);
  216. this.firstRangeAverageSize = Math.round(this.firstRangeTotalSize / this.sizes.size);
  217. } else {
  218. delete this.firstRangeTotalSize;
  219. }
  220. }
  221. }
  222. // in some special situation (e.g. length change) we need to update in a row
  223. // try goiong to render next range by a leading buffer according to current direction
  224. }, {
  225. key: "handleDataSourcesChange",
  226. value: function handleDataSourcesChange() {
  227. var start = this.range.start;
  228. if (this.isFront()) {
  229. start = start - LEADING_BUFFER;
  230. } else if (this.isBehind()) {
  231. start = start + LEADING_BUFFER;
  232. }
  233. start = Math.max(start, 0);
  234. this.updateRange(this.range.start, this.getEndByStart(start));
  235. }
  236. // when slot size change, we also need force update
  237. }, {
  238. key: "handleSlotSizeChange",
  239. value: function handleSlotSizeChange() {
  240. this.handleDataSourcesChange();
  241. }
  242. // calculating range on scroll
  243. }, {
  244. key: "handleScroll",
  245. value: function handleScroll(offset) {
  246. this.direction = offset < this.offset ? DIRECTION_TYPE.FRONT : DIRECTION_TYPE.BEHIND;
  247. this.offset = offset;
  248. if (!this.param) {
  249. return;
  250. }
  251. if (this.direction === DIRECTION_TYPE.FRONT) {
  252. this.handleFront();
  253. } else if (this.direction === DIRECTION_TYPE.BEHIND) {
  254. this.handleBehind();
  255. }
  256. }
  257. // ----------- public method end -----------
  258. }, {
  259. key: "handleFront",
  260. value: function handleFront() {
  261. var overs = this.getScrollOvers();
  262. if (overs > this.range.start) {
  263. return;
  264. }
  265. var start = Math.max(overs - this.param.buffer, 0);
  266. this.checkRange(start, this.getEndByStart(start));
  267. }
  268. }, {
  269. key: "handleBehind",
  270. value: function handleBehind() {
  271. var overs = this.getScrollOvers();
  272. if (overs < this.range.start + this.param.buffer) {
  273. return;
  274. }
  275. this.checkRange(overs, this.getEndByStart(overs));
  276. }
  277. // return the pass overs according to current scroll offset
  278. }, {
  279. key: "getScrollOvers",
  280. value: function getScrollOvers() {
  281. var offset = this.offset - this.param.slotHeaderSize;
  282. if (offset <= 0) {
  283. return 0;
  284. }
  285. if (this.isFixedType()) {
  286. return Math.floor(offset / this.fixedSizeValue);
  287. }
  288. var low = 0;
  289. var middle = 0;
  290. var middleOffset = 0;
  291. var high = this.param.uniqueIds.length;
  292. while (low <= high) {
  293. middle = low + Math.floor((high - low) / 2);
  294. middleOffset = this.getIndexOffset(middle);
  295. if (middleOffset === offset) {
  296. return middle;
  297. } else if (middleOffset < offset) {
  298. low = middle + 1;
  299. } else if (middleOffset > offset) {
  300. high = middle - 1;
  301. }
  302. }
  303. return low > 0 ? --low : 0;
  304. }
  305. // return a scroll offset from given index, can efficiency be improved more here?
  306. // although the call frequency is very high, its only a superposition of numbers
  307. }, {
  308. key: "getIndexOffset",
  309. value: function getIndexOffset(givenIndex) {
  310. if (!givenIndex) {
  311. return 0;
  312. }
  313. var offset = 0;
  314. var indexSize = 0;
  315. for (var index = 0; index < givenIndex; index++) {
  316. indexSize = this.sizes.get(this.param.uniqueIds[index]);
  317. offset = offset + (typeof indexSize === "number" ? indexSize : this.getEstimateSize());
  318. }
  319. this.lastCalcIndex = Math.max(this.lastCalcIndex, givenIndex - 1);
  320. this.lastCalcIndex = Math.min(this.lastCalcIndex, this.getLastIndex());
  321. return offset;
  322. }
  323. // is fixed size type
  324. }, {
  325. key: "isFixedType",
  326. value: function isFixedType() {
  327. return this.calcType === CALC_TYPE.FIXED;
  328. }
  329. // return the real last index
  330. }, {
  331. key: "getLastIndex",
  332. value: function getLastIndex() {
  333. return this.param.uniqueIds.length - 1;
  334. }
  335. // in some conditions range is broke, we need correct it
  336. // and then decide whether need update to next range
  337. }, {
  338. key: "checkRange",
  339. value: function checkRange(start, end) {
  340. var keeps = this.param.keeps;
  341. var total = this.param.uniqueIds.length;
  342. if (total <= keeps) {
  343. start = 0;
  344. end = this.getLastIndex();
  345. } else if (end - start < keeps - 1) {
  346. start = end - keeps + 1;
  347. }
  348. if (this.range.start !== start) {
  349. this.updateRange(start, end);
  350. }
  351. }
  352. // setting to a new range and rerender
  353. }, {
  354. key: "updateRange",
  355. value: function updateRange(start, end) {
  356. this.range.start = start;
  357. this.range.end = end;
  358. this.range.padFront = this.getPadFront();
  359. this.range.padBehind = this.getPadBehind();
  360. this.callUpdate(this.getRange());
  361. }
  362. // return end base on start
  363. }, {
  364. key: "getEndByStart",
  365. value: function getEndByStart(start) {
  366. var theoryEnd = start + this.param.keeps - 1;
  367. var truelyEnd = Math.min(theoryEnd, this.getLastIndex());
  368. return truelyEnd;
  369. }
  370. // return total front offset
  371. }, {
  372. key: "getPadFront",
  373. value: function getPadFront() {
  374. if (this.isFixedType()) {
  375. return this.fixedSizeValue * this.range.start;
  376. } else {
  377. return this.getIndexOffset(this.range.start);
  378. }
  379. }
  380. // return total behind offset
  381. }, {
  382. key: "getPadBehind",
  383. value: function getPadBehind() {
  384. var end = this.range.end;
  385. var lastIndex = this.getLastIndex();
  386. if (this.isFixedType()) {
  387. return (lastIndex - end) * this.fixedSizeValue;
  388. }
  389. if (this.lastCalcIndex === lastIndex) {
  390. return this.getIndexOffset(lastIndex) - this.getIndexOffset(end);
  391. } else {
  392. return (lastIndex - end) * this.getEstimateSize();
  393. }
  394. }
  395. // get the item estimate size
  396. }, {
  397. key: "getEstimateSize",
  398. value: function getEstimateSize() {
  399. return this.isFixedType() ? this.fixedSizeValue : this.firstRangeAverageSize || this.param.estimateSize;
  400. }
  401. }]);
  402. return Virtual2;
  403. }();
  404. var VirtualProps = {
  405. dataKey: {
  406. type: [String, Function],
  407. required: true
  408. },
  409. dataSources: {
  410. type: Array,
  411. required: true,
  412. "default": function _default() {
  413. return [];
  414. }
  415. },
  416. dataComponent: {
  417. type: [Object, Function],
  418. required: true
  419. },
  420. keeps: {
  421. type: Number,
  422. "default": 30
  423. },
  424. extraProps: {
  425. type: Object
  426. },
  427. estimateSize: {
  428. type: Number,
  429. "default": 50
  430. },
  431. direction: {
  432. type: String,
  433. "default": "vertical"
  434. // the other value is horizontal
  435. },
  436. start: {
  437. type: Number,
  438. "default": 0
  439. },
  440. offset: {
  441. type: Number,
  442. "default": 0
  443. },
  444. topThreshold: {
  445. type: Number,
  446. "default": 0
  447. },
  448. bottomThreshold: {
  449. type: Number,
  450. "default": 0
  451. },
  452. pageMode: {
  453. type: Boolean,
  454. "default": false
  455. },
  456. rootTag: {
  457. type: String,
  458. "default": "div"
  459. },
  460. wrapTag: {
  461. type: String,
  462. "default": "div"
  463. },
  464. wrapClass: {
  465. type: String,
  466. "default": "wrap"
  467. },
  468. wrapStyle: {
  469. type: Object
  470. },
  471. itemTag: {
  472. type: String,
  473. "default": "div"
  474. },
  475. itemClass: {
  476. type: String,
  477. "default": ""
  478. },
  479. itemClassAdd: {
  480. type: Function
  481. },
  482. itemStyle: {
  483. type: Object
  484. },
  485. headerTag: {
  486. type: String,
  487. "default": "div"
  488. },
  489. headerClass: {
  490. type: String,
  491. "default": ""
  492. },
  493. headerStyle: {
  494. type: Object
  495. },
  496. footerTag: {
  497. type: String,
  498. "default": "div"
  499. },
  500. footerClass: {
  501. type: String,
  502. "default": ""
  503. },
  504. footerStyle: {
  505. type: Object
  506. },
  507. itemScopedSlots: {
  508. type: Object
  509. }
  510. };
  511. var ItemProps = {
  512. index: {
  513. type: Number
  514. },
  515. event: {
  516. type: String
  517. },
  518. tag: {
  519. type: String
  520. },
  521. horizontal: {
  522. type: Boolean
  523. },
  524. source: {
  525. type: Object
  526. },
  527. component: {
  528. type: [Object, Function]
  529. },
  530. uniqueKey: {
  531. type: [String, Number]
  532. },
  533. extraProps: {
  534. type: Object
  535. },
  536. scopedSlots: {
  537. type: Object
  538. }
  539. };
  540. var SlotProps = {
  541. event: {
  542. type: String
  543. },
  544. uniqueKey: {
  545. type: String
  546. },
  547. tag: {
  548. type: String
  549. },
  550. horizontal: {
  551. type: Boolean
  552. }
  553. };
  554. var useResizeChange = function useResizeChange2(props, rootRef, emit) {
  555. var resizeObserver = null;
  556. var shapeKey = vue.computed(function() {
  557. return props.horizontal ? "offsetWidth" : "offsetHeight";
  558. });
  559. var getCurrentSize = function getCurrentSize2() {
  560. return rootRef.value ? rootRef.value[shapeKey.value] : 0;
  561. };
  562. var dispatchSizeChange = function dispatchSizeChange2() {
  563. var event = props.event, uniqueKey = props.uniqueKey, hasInitial = props.hasInitial;
  564. emit(event, uniqueKey, getCurrentSize(), hasInitial);
  565. };
  566. vue.onMounted(function() {
  567. if (typeof ResizeObserver !== "undefined") {
  568. resizeObserver = new ResizeObserver(function() {
  569. dispatchSizeChange();
  570. });
  571. rootRef.value && resizeObserver.observe(rootRef.value);
  572. }
  573. });
  574. vue.onUpdated(function() {
  575. dispatchSizeChange();
  576. });
  577. vue.onUnmounted(function() {
  578. if (resizeObserver) {
  579. resizeObserver.disconnect();
  580. resizeObserver = null;
  581. }
  582. });
  583. };
  584. var Item$1 = vue.defineComponent({
  585. name: "VirtualListItem",
  586. props: ItemProps,
  587. emits: ["itemResize"],
  588. setup: function setup(props, _ref) {
  589. var emit = _ref.emit;
  590. var rootRef = vue.ref(null);
  591. useResizeChange(props, rootRef, emit);
  592. return function() {
  593. var Tag = props.tag, Comp = props.component, _props$extraProps = props.extraProps, extraProps = _props$extraProps === void 0 ? {} : _props$extraProps, index = props.index, source = props.source, _props$scopedSlots = props.scopedSlots, scopedSlots = _props$scopedSlots === void 0 ? {} : _props$scopedSlots, uniqueKey = props.uniqueKey;
  594. var mergedProps = _objectSpread2(_objectSpread2({}, extraProps), {}, {
  595. source,
  596. index
  597. });
  598. return vue.createVNode(Tag, {
  599. "key": uniqueKey,
  600. "ref": rootRef
  601. }, {
  602. "default": function _default2() {
  603. return [vue.createVNode(Comp, _objectSpread2(_objectSpread2({}, mergedProps), {}, {
  604. "scopedSlots": scopedSlots
  605. }), null)];
  606. }
  607. });
  608. };
  609. }
  610. });
  611. var Slot = vue.defineComponent({
  612. name: "VirtualListSlot",
  613. props: SlotProps,
  614. emits: ["slotResize"],
  615. setup: function setup2(props, _ref2) {
  616. var slots = _ref2.slots, emit = _ref2.emit;
  617. var rootRef = vue.ref(null);
  618. useResizeChange(props, rootRef, emit);
  619. return function() {
  620. var _slots$default;
  621. var Tag = props.tag, uniqueKey = props.uniqueKey;
  622. return vue.createVNode(Tag, {
  623. "ref": rootRef,
  624. "key": uniqueKey
  625. }, {
  626. "default": function _default2() {
  627. return [(_slots$default = slots["default"]) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)];
  628. }
  629. });
  630. };
  631. }
  632. });
  633. var EVENT_TYPE;
  634. (function(EVENT_TYPE2) {
  635. EVENT_TYPE2["ITEM"] = "itemResize";
  636. EVENT_TYPE2["SLOT"] = "slotResize";
  637. })(EVENT_TYPE || (EVENT_TYPE = {}));
  638. var SLOT_TYPE;
  639. (function(SLOT_TYPE2) {
  640. SLOT_TYPE2["HEADER"] = "thead";
  641. SLOT_TYPE2["FOOTER"] = "tfoot";
  642. })(SLOT_TYPE || (SLOT_TYPE = {}));
  643. var VirtualList = vue.defineComponent({
  644. name: "VirtualList",
  645. props: VirtualProps,
  646. setup: function setup3(props, _ref) {
  647. var emit = _ref.emit, slots = _ref.slots, expose = _ref.expose;
  648. var isHorizontal = props.direction === "horizontal";
  649. var directionKey = isHorizontal ? "scrollLeft" : "scrollTop";
  650. var range = vue.ref(null);
  651. var root = vue.ref();
  652. var shepherd = vue.ref(null);
  653. var virtual;
  654. vue.watch(function() {
  655. return props.dataSources.length;
  656. }, function() {
  657. virtual.updateParam("uniqueIds", getUniqueIdFromDataSources());
  658. virtual.handleDataSourcesChange();
  659. });
  660. vue.watch(function() {
  661. return props.keeps;
  662. }, function(newValue) {
  663. virtual.updateParam("keeps", newValue);
  664. virtual.handleSlotSizeChange();
  665. });
  666. vue.watch(function() {
  667. return props.start;
  668. }, function(newValue) {
  669. scrollToIndex(newValue);
  670. });
  671. vue.watch(function() {
  672. return props.offset;
  673. }, function(newValue) {
  674. return scrollToOffset(newValue);
  675. });
  676. var getSize = function getSize2(id) {
  677. return virtual.sizes.get(id);
  678. };
  679. var getOffset = function getOffset2() {
  680. if (props.pageMode) {
  681. return document.documentElement[directionKey] || document.body[directionKey];
  682. } else {
  683. return root.value ? Math.ceil(root.value[directionKey]) : 0;
  684. }
  685. };
  686. var getClientSize = function getClientSize2() {
  687. var key = isHorizontal ? "clientWidth" : "clientHeight";
  688. if (props.pageMode) {
  689. return document.documentElement[key] || document.body[key];
  690. } else {
  691. return root.value ? Math.ceil(root.value[key]) : 0;
  692. }
  693. };
  694. var getScrollSize = function getScrollSize2() {
  695. var key = isHorizontal ? "scrollWidth" : "scrollHeight";
  696. if (props.pageMode) {
  697. return document.documentElement[key] || document.body[key];
  698. } else {
  699. return root.value ? Math.ceil(root.value[key]) : 0;
  700. }
  701. };
  702. var emitEvent = function emitEvent2(offset, clientSize, scrollSize, evt) {
  703. emit("scroll", evt, virtual.getRange());
  704. if (virtual.isFront() && !!props.dataSources.length && offset - props.topThreshold <= 0) {
  705. emit("totop");
  706. } else if (virtual.isBehind() && offset + clientSize + props.bottomThreshold >= scrollSize) {
  707. emit("tobottom");
  708. }
  709. };
  710. var onScroll = function onScroll2(evt) {
  711. var offset = getOffset();
  712. var clientSize = getClientSize();
  713. var scrollSize = getScrollSize();
  714. if (offset < 0 || offset + clientSize > scrollSize + 1 || !scrollSize) {
  715. return;
  716. }
  717. virtual.handleScroll(offset);
  718. emitEvent(offset, clientSize, scrollSize, evt);
  719. };
  720. var getUniqueIdFromDataSources = function getUniqueIdFromDataSources2() {
  721. var dataKey = props.dataKey, _props$dataSources = props.dataSources, dataSources = _props$dataSources === void 0 ? [] : _props$dataSources;
  722. return dataSources.map(function(dataSource) {
  723. return typeof dataKey === "function" ? dataKey(dataSource) : dataSource[dataKey];
  724. });
  725. };
  726. var onRangeChanged = function onRangeChanged2(newRange) {
  727. range.value = newRange;
  728. };
  729. var installVirtual = function installVirtual2() {
  730. virtual = new Virtual({
  731. slotHeaderSize: 0,
  732. slotFooterSize: 0,
  733. keeps: props.keeps,
  734. estimateSize: props.estimateSize,
  735. buffer: Math.round(props.keeps / 3),
  736. // recommend for a third of keeps
  737. uniqueIds: getUniqueIdFromDataSources()
  738. }, onRangeChanged);
  739. range.value = virtual.getRange();
  740. };
  741. var scrollToIndex = function scrollToIndex2(index) {
  742. if (index >= props.dataSources.length - 1) {
  743. scrollToBottom();
  744. } else {
  745. var offset = virtual.getOffset(index);
  746. scrollToOffset(offset);
  747. }
  748. };
  749. var scrollToOffset = function scrollToOffset2(offset) {
  750. if (props.pageMode) {
  751. document.body[directionKey] = offset;
  752. document.documentElement[directionKey] = offset;
  753. } else {
  754. if (root.value) {
  755. root.value[directionKey] = offset;
  756. }
  757. }
  758. };
  759. var getRenderSlots = function getRenderSlots2() {
  760. var slots2 = [];
  761. var _range$value = range.value, start = _range$value.start, end = _range$value.end;
  762. var dataSources = props.dataSources, dataKey = props.dataKey, itemClass = props.itemClass, itemTag = props.itemTag, itemStyle = props.itemStyle, extraProps = props.extraProps, dataComponent = props.dataComponent, itemScopedSlots = props.itemScopedSlots;
  763. for (var index = start; index <= end; index++) {
  764. var dataSource = dataSources[index];
  765. if (dataSource) {
  766. var uniqueKey = typeof dataKey === "function" ? dataKey(dataSource) : dataSource[dataKey];
  767. if (typeof uniqueKey === "string" || typeof uniqueKey === "number") {
  768. slots2.push(vue.createVNode(Item$1, {
  769. "index": index,
  770. "tag": itemTag,
  771. "event": EVENT_TYPE.ITEM,
  772. "horizontal": isHorizontal,
  773. "uniqueKey": uniqueKey,
  774. "source": dataSource,
  775. "extraProps": extraProps,
  776. "component": dataComponent,
  777. "scopedSlots": itemScopedSlots,
  778. "style": itemStyle,
  779. "class": "".concat(itemClass).concat(props.itemClassAdd ? " " + props.itemClassAdd(index) : ""),
  780. "onItemResize": onItemResized
  781. }, null));
  782. } else {
  783. console.warn("Cannot get the data-key '".concat(dataKey, "' from data-sources."));
  784. }
  785. } else {
  786. console.warn("Cannot get the index '".concat(index, "' from data-sources."));
  787. }
  788. }
  789. return slots2;
  790. };
  791. var onItemResized = function onItemResized2(id, size) {
  792. virtual.saveSize(id, size);
  793. emit("resized", id, size);
  794. };
  795. var onSlotResized = function onSlotResized2(type, size, hasInit) {
  796. if (type === SLOT_TYPE.HEADER) {
  797. virtual.updateParam("slotHeaderSize", size);
  798. } else if (type === SLOT_TYPE.FOOTER) {
  799. virtual.updateParam("slotFooterSize", size);
  800. }
  801. if (hasInit) {
  802. virtual.handleSlotSizeChange();
  803. }
  804. };
  805. var scrollToBottom = function scrollToBottom2() {
  806. if (shepherd.value) {
  807. var offset = shepherd.value[isHorizontal ? "offsetLeft" : "offsetTop"];
  808. scrollToOffset(offset);
  809. setTimeout(function() {
  810. if (getOffset() + getClientSize() < getScrollSize()) {
  811. scrollToBottom2();
  812. }
  813. }, 3);
  814. }
  815. };
  816. var updatePageModeFront = function updatePageModeFront2() {
  817. if (root.value) {
  818. var rect = root.value.getBoundingClientRect();
  819. var defaultView = root.value.ownerDocument.defaultView;
  820. var offsetFront = isHorizontal ? rect.left + defaultView.pageXOffset : rect.top + defaultView.pageYOffset;
  821. virtual.updateParam("slotHeaderSize", offsetFront);
  822. }
  823. };
  824. var getSizes = function getSizes2() {
  825. return virtual.sizes.size;
  826. };
  827. vue.onBeforeMount(function() {
  828. installVirtual();
  829. });
  830. vue.onActivated(function() {
  831. scrollToOffset(virtual.offset);
  832. });
  833. vue.onMounted(function() {
  834. if (props.start) {
  835. scrollToIndex(props.start);
  836. } else if (props.offset) {
  837. scrollToOffset(props.offset);
  838. }
  839. if (props.pageMode) {
  840. updatePageModeFront();
  841. document.addEventListener("scroll", onScroll, {
  842. passive: false
  843. });
  844. }
  845. });
  846. vue.onUnmounted(function() {
  847. virtual.destroy();
  848. if (props.pageMode) {
  849. document.removeEventListener("scroll", onScroll);
  850. }
  851. });
  852. expose({
  853. scrollToBottom,
  854. getSizes,
  855. getSize,
  856. getOffset,
  857. getScrollSize,
  858. getClientSize,
  859. scrollToOffset,
  860. scrollToIndex
  861. });
  862. return function() {
  863. var pageMode = props.pageMode, RootTag = props.rootTag, WrapTag = props.wrapTag, wrapClass = props.wrapClass, wrapStyle = props.wrapStyle, headerTag = props.headerTag, headerClass = props.headerClass, headerStyle = props.headerStyle, footerTag = props.footerTag, footerClass = props.footerClass, footerStyle = props.footerStyle;
  864. var _ref2 = range.value, padFront = _ref2.padFront, padBehind = _ref2.padBehind;
  865. var paddingStyle = {
  866. padding: isHorizontal ? "0px ".concat(padBehind, "px 0px ").concat(padFront, "px") : "".concat(padFront, "px 0px ").concat(padBehind, "px")
  867. };
  868. var wrapperStyle = wrapStyle ? Object.assign({}, wrapStyle, paddingStyle) : paddingStyle;
  869. var header = slots.header, footer = slots.footer;
  870. return vue.createVNode(RootTag, {
  871. "ref": root,
  872. "onScroll": !pageMode && onScroll
  873. }, {
  874. "default": function _default2() {
  875. return [header && vue.createVNode(Slot, {
  876. "class": headerClass,
  877. "style": headerStyle,
  878. "tag": headerTag,
  879. "event": EVENT_TYPE.SLOT,
  880. "uniqueKey": SLOT_TYPE.HEADER,
  881. "onSlotResize": onSlotResized
  882. }, {
  883. "default": function _default3() {
  884. return [header()];
  885. }
  886. }), vue.createVNode(WrapTag, {
  887. "class": wrapClass,
  888. "style": wrapperStyle
  889. }, {
  890. "default": function _default3() {
  891. return [getRenderSlots()];
  892. }
  893. }), footer && vue.createVNode(Slot, {
  894. "class": footerClass,
  895. "style": footerStyle,
  896. "tag": footerTag,
  897. "event": EVENT_TYPE.SLOT,
  898. "uniqueKey": SLOT_TYPE.FOOTER,
  899. "onSlotResize": onSlotResized
  900. }, {
  901. "default": function _default3() {
  902. return [footer()];
  903. }
  904. }), vue.createVNode("div", {
  905. "ref": shepherd,
  906. "style": {
  907. width: isHorizontal ? "0px" : "100%",
  908. height: isHorizontal ? "100%" : "0px"
  909. }
  910. }, null)];
  911. }
  912. });
  913. };
  914. }
  915. });
  916. const _export_sfc = (sfc, props) => {
  917. const target = sfc.__vccOpts || sfc;
  918. for (const [key, val] of props) {
  919. target[key] = val;
  920. }
  921. return target;
  922. };
  923. const _hoisted_1$1 = { class: "head" };
  924. const _hoisted_2 = { class: "index" };
  925. const _hoisted_3 = ["title"];
  926. const _sfc_main$2 = {
  927. __name: "Item",
  928. props: {
  929. source: {
  930. type: Object,
  931. default: () => ({})
  932. }
  933. },
  934. setup(__props) {
  935. const props = __props;
  936. const handleClick = () => {
  937. const url = props.source.url;
  938. const parser = new DOMParser();
  939. const oldTopo = document.getElementsByClassName("list-infinite")[0].scrollTop;
  940. fetch(url).then(function(response) {
  941. return response.text();
  942. }).then(function(html) {
  943. const doc = parser.parseFromString(html, "text/html");
  944. const app = document.getElementById("app");
  945. document.body = doc.body;
  946. document.body.appendChild(app);
  947. document.getElementsByClassName("list-infinite")[0].scrollTop = oldTopo;
  948. }).catch(function(error) {
  949. console.error("Failed to load issue:", error);
  950. });
  951. history.pushState({}, "", url);
  952. };
  953. return (_ctx, _cache) => {
  954. return vue.openBlock(), vue.createElementBlock("div", {
  955. class: "item-inner",
  956. onClick: handleClick
  957. }, [
  958. vue.createElementVNode("div", _hoisted_1$1, [
  959. vue.createElementVNode("div", _hoisted_2, vue.toDisplayString(__props.source.index), 1),
  960. vue.createElementVNode("div", {
  961. class: "name",
  962. title: __props.source.text
  963. }, vue.toDisplayString(__props.source.text), 9, _hoisted_3)
  964. ])
  965. ]);
  966. };
  967. }
  968. };
  969. const Item = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-8ef0fbfc"]]);
  970. const _withScopeId = (n) => (vue.pushScopeId("data-v-8e8d3fd2"), n = n(), vue.popScopeId(), n);
  971. const _hoisted_1 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "loader" }, "已经到底了", -1));
  972. const _sfc_main$1 = {
  973. __name: "IssueSidebar",
  974. setup(__props) {
  975. let currentPage = 1;
  976. let hasFinished = vue.ref(false);
  977. const listData = vue.ref([]);
  978. const onScrollToTop = () => {
  979. console.log("at top");
  980. };
  981. const onScrollToBottom = () => {
  982. console.log("at bottom");
  983. requestData();
  984. };
  985. vue.onMounted(() => {
  986. requestData();
  987. });
  988. function requestData() {
  989. const url = `https://github.com${window.location.pathname.replace(/\/issues\/.*/, "/issues")}?page=${currentPage}&q=is%3Aissue`;
  990. fetch(url).then(function(response) {
  991. return response.text();
  992. }).then(function(html) {
  993. const parser = new DOMParser();
  994. const doc = parser.parseFromString(html, "text/html");
  995. const issueLinks = doc.querySelectorAll(".js-navigation-open");
  996. const len = listData.value.length;
  997. if (!issueLinks.length) {
  998. hasFinished.value = true;
  999. } else {
  1000. listData.value = listData.value.concat(Array.from(issueLinks).map((v, i) => {
  1001. return {
  1002. index: len + i + 1,
  1003. text: v.innerText,
  1004. url: v.href
  1005. };
  1006. }));
  1007. currentPage++;
  1008. }
  1009. }).catch(function(error) {
  1010. console.error("Failed to load issues:", error);
  1011. });
  1012. }
  1013. return (_ctx, _cache) => {
  1014. return vue.openBlock(), vue.createBlock(vue.unref(VirtualList), {
  1015. class: "list-infinite",
  1016. "data-key": "index",
  1017. "data-sources": listData.value,
  1018. "data-component": Item,
  1019. "estimate-size": 70,
  1020. "item-class": "list-item-infinite",
  1021. "footer-class": "loader-wrapper",
  1022. onTotop: onScrollToTop,
  1023. onTobottom: onScrollToBottom
  1024. }, vue.createSlots({ _: 2 }, [
  1025. vue.unref(hasFinished) ? {
  1026. name: "footer",
  1027. fn: vue.withCtx(() => [
  1028. _hoisted_1
  1029. ]),
  1030. key: "0"
  1031. } : void 0
  1032. ]), 1032, ["data-sources"]);
  1033. };
  1034. }
  1035. };
  1036. const IssueSidebar = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-8e8d3fd2"]]);
  1037. const _sfc_main = {
  1038. __name: "App",
  1039. setup(__props) {
  1040. let tamp = null;
  1041. let currentUrl = "";
  1042. const showIssueTab = vue.ref(false);
  1043. const reg = /\/issues/;
  1044. vue.onMounted(() => {
  1045. tamp = setInterval(function() {
  1046. if (window.location.href !== currentUrl) {
  1047. console.log("URL发生变化");
  1048. if (reg.test(window.location.href)) {
  1049. showIssueTab.value = true;
  1050. document.documentElement.classList.add("issue-active");
  1051. document.getElementById("app").classList.add("active");
  1052. } else {
  1053. showIssueTab.value = false;
  1054. document.documentElement.classList.remove("issue-active");
  1055. document.getElementById("app").classList.remove("active");
  1056. }
  1057. currentUrl = window.location.href;
  1058. }
  1059. }, 500);
  1060. });
  1061. vue.onUnmounted(() => {
  1062. clearInterval(tamp);
  1063. });
  1064. return (_ctx, _cache) => {
  1065. return showIssueTab.value ? (vue.openBlock(), vue.createBlock(IssueSidebar, { key: 0 })) : vue.createCommentVNode("", true);
  1066. };
  1067. }
  1068. };
  1069. vue.createApp(_sfc_main).mount(
  1070. (() => {
  1071. const app = document.createElement("div");
  1072. app.id = "app";
  1073. document.body.append(app);
  1074. return app;
  1075. })()
  1076. );
  1077.  
  1078. })(Vue);

QingJ © 2025

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