rj-code-preview

Make RJ code great again!

目前为 2023-01-11 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name rj-code-preview
  3. // @author SettingDust
  4. // @description Make RJ code great again!
  5. // @grant GM_addElement
  6. // @grant GM_xmlhttpRequest
  7. // @grant GM_setValue
  8. // @grant GM_getValue
  9. // @inject-into auto
  10. // @match *://*/*
  11. // @namespace SettingDust
  12. // @run-at document-end
  13. // @version 3.0.4
  14. // ==/UserScript==
  15.  
  16. // src/fetch-rj.ts
  17. var productPage = (rj) => `https://www.dlsite.com/maniax/work/=/product_id/${rj}.html`, agings = {
  18. adult: "18 \u7981",
  19. general: "\u5168\u5E74\u9F84"
  20. };
  21. function productInfo(rj) {
  22. return new Promise((resolve, reject) => {
  23. GM_xmlhttpRequest({
  24. url: `https://www.dlsite.com/maniax/api/=/product.json?workno=${rj}`,
  25. responseType: "json",
  26. onload: function(resp) {
  27. resp.readyState === 4 && resp.status === 200 ? (resolve(resp.response[0]), console.debug("[rj-code-preview/product]", resp.response[0])) : reject(resp);
  28. }
  29. });
  30. });
  31. }
  32. function productRatingInfo(rj) {
  33. return new Promise((resolve, reject) => {
  34. GM_xmlhttpRequest({
  35. url: `https://www.dlsite.com/maniax/product/info/ajax?product_id=${rj}`,
  36. responseType: "json",
  37. onload: function(resp) {
  38. resp.readyState === 4 && resp.status === 200 ? (resolve(resp.response[rj]), console.debug("[rj-code-preview/rating]", resp.response[rj])) : reject(resp);
  39. }
  40. });
  41. });
  42. }
  43. function fetch_rj_default(rj) {
  44. return new Promise((resolve, reject) => {
  45. Promise.all([productInfo(rj), productRatingInfo(rj)]).then(
  46. ([product, rating]) => {
  47. var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
  48. return {
  49. name: product.work_name,
  50. image: (_a = product.image_main) == null ? void 0 : _a.url,
  51. type: product.work_type_string,
  52. group: product.maker_name,
  53. date: product.regist_date,
  54. series: product.title_name,
  55. age: (_b = agings[product.age_category_string]) != null ? _b : product.age_category_string,
  56. voices: (_d = (_c = product.creaters) == null ? void 0 : _c.voice_by) == null ? void 0 : _d.map((it) => it.name),
  57. illusts: (_f = (_e = product.creaters) == null ? void 0 : _e.illust_by) == null ? void 0 : _f.map((it) => it.name),
  58. scenarios: (_h = (_g = product.creaters) == null ? void 0 : _g.scenario_by) == null ? void 0 : _h.map((it) => it.name),
  59. creators: (_j = (_i = product.creaters) == null ? void 0 : _i.created_by) == null ? void 0 : _j.map((it) => it.name),
  60. musics: (_l = (_k = product.creaters) == null ? void 0 : _k.music_by) == null ? void 0 : _l.map((it) => it.name),
  61. hasCreators: (_n = (_m = product.creaters) == null ? void 0 : _m.created_by) == null ? void 0 : _n.length,
  62. hasScenarios: (_p = (_o = product.creaters) == null ? void 0 : _o.scenario_by) == null ? void 0 : _p.length,
  63. hasIllusts: (_r = (_q = product.creaters) == null ? void 0 : _q.illust_by) == null ? void 0 : _r.length,
  64. hasVoices: (_t = (_s = product.creaters) == null ? void 0 : _s.voice_by) == null ? void 0 : _t.length,
  65. hasMusics: (_v = (_u = product.creaters) == null ? void 0 : _u.music_by) == null ? void 0 : _v.length,
  66. tags: (_w = product.genres) == null ? void 0 : _w.map((it) => it.name),
  67. hasTags: (_x = product.genres) == null ? void 0 : _x.length,
  68. rating: rating.rate_average_2dp,
  69. sale: rating.dl_count
  70. };
  71. }
  72. ).then((it) => {
  73. GM_setValue(rj, it), resolve(it);
  74. }).catch(reject);
  75. let cache = GM_getValue(rj);
  76. cache && (console.debug(`[rj-code-preview/cached/${rj}]`), resolve(cache));
  77. });
  78. }
  79.  
  80. // src/hack-rj-code.ts
  81. var RJ_CODE_LINK_CLASS = "rj-code", RJ_CODE_ATTRIBUTE = "rjCode", RJ_REGEX = new RegExp("R[JE][0-9]{6,8}", "gi");
  82. function wrapRJCode(rj) {
  83. let a = document.createElement("a");
  84. return a.classList.add(RJ_CODE_LINK_CLASS), a.href = productPage(rj), a.innerHTML = rj, a.target = "_blank", a.rel = "noreferrer", a.dataset[RJ_CODE_ATTRIBUTE] = rj, a;
  85. }
  86. function injectRJCode(node) {
  87. var _a, _b;
  88. let text = node.nodeValue, matches = [], match;
  89. for (; match = RJ_REGEX.exec(text); )
  90. matches.push({
  91. index: match.index,
  92. value: match[0]
  93. });
  94. node.nodeValue = text.substring(0, matches[0].index);
  95. let prev = null;
  96. for (let i = 0; i < matches.length; i++) {
  97. let match2 = matches[i], a = wrapRJCode(match2.value);
  98. node.parentNode.insertBefore(
  99. a,
  100. (_a = prev == null ? void 0 : prev.nextSibling) != null ? _a : node.nextSibling
  101. );
  102. let nextIndex = (_b = matches[i + 1]) == null ? void 0 : _b.index, afterText = text.substring(match2.index + match2.value.length, nextIndex);
  103. if (afterText) {
  104. let afterNode = document.createTextNode(afterText);
  105. node.parentNode.insertBefore(afterNode, a.nextElementSibling), prev = afterNode;
  106. } else
  107. prev = a;
  108. }
  109. }
  110. function hack_rj_code_default(root) {
  111. let walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
  112. acceptNode(node) {
  113. if (node.parentElement.classList.contains(RJ_CODE_LINK_CLASS) || node.nodeValue.match(RJ_REGEX))
  114. return NodeFilter.FILTER_ACCEPT;
  115. }
  116. });
  117. for (; walker.nextNode(); ) {
  118. let node = walker.currentNode;
  119. node.parentElement.classList.contains(RJ_CODE_LINK_CLASS) || injectRJCode(node);
  120. }
  121. }
  122.  
  123. // node_modules/.pnpm/mustache@4.2.0/node_modules/mustache/mustache.mjs
  124. var objectToString = Object.prototype.toString, isArray = Array.isArray || function(object) {
  125. return objectToString.call(object) === "[object Array]";
  126. };
  127. function isFunction(object) {
  128. return typeof object == "function";
  129. }
  130. function typeStr(obj) {
  131. return isArray(obj) ? "array" : typeof obj;
  132. }
  133. function escapeRegExp(string) {
  134. return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
  135. }
  136. function hasProperty(obj, propName) {
  137. return obj != null && typeof obj == "object" && propName in obj;
  138. }
  139. function primitiveHasOwnProperty(primitive, propName) {
  140. return primitive != null && typeof primitive != "object" && primitive.hasOwnProperty && primitive.hasOwnProperty(propName);
  141. }
  142. var regExpTest = RegExp.prototype.test;
  143. function testRegExp(re, string) {
  144. return regExpTest.call(re, string);
  145. }
  146. var nonSpaceRe = /\S/;
  147. function isWhitespace(string) {
  148. return !testRegExp(nonSpaceRe, string);
  149. }
  150. var entityMap = {
  151. "&": "&amp;",
  152. "<": "&lt;",
  153. ">": "&gt;",
  154. '"': "&quot;",
  155. "'": "&#39;",
  156. "/": "&#x2F;",
  157. "`": "&#x60;",
  158. "=": "&#x3D;"
  159. };
  160. function escapeHtml(string) {
  161. return String(string).replace(/[&<>"'`=\/]/g, function(s) {
  162. return entityMap[s];
  163. });
  164. }
  165. var whiteRe = /\s*/, spaceRe = /\s+/, equalsRe = /\s*=/, curlyRe = /\s*\}/, tagRe = /#|\^|\/|>|\{|&|=|!/;
  166. function parseTemplate(template2, tags) {
  167. if (!template2)
  168. return [];
  169. var lineHasNonSpace = !1, sections = [], tokens = [], spaces = [], hasTag = !1, nonSpace = !1, indentation = "", tagIndex = 0;
  170. function stripSpace() {
  171. if (hasTag && !nonSpace)
  172. for (; spaces.length; )
  173. delete tokens[spaces.pop()];
  174. else
  175. spaces = [];
  176. hasTag = !1, nonSpace = !1;
  177. }
  178. var openingTagRe, closingTagRe, closingCurlyRe;
  179. function compileTags(tagsToCompile) {
  180. if (typeof tagsToCompile == "string" && (tagsToCompile = tagsToCompile.split(spaceRe, 2)), !isArray(tagsToCompile) || tagsToCompile.length !== 2)
  181. throw new Error("Invalid tags: " + tagsToCompile);
  182. openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + "\\s*"), closingTagRe = new RegExp("\\s*" + escapeRegExp(tagsToCompile[1])), closingCurlyRe = new RegExp("\\s*" + escapeRegExp("}" + tagsToCompile[1]));
  183. }
  184. compileTags(tags || mustache.tags);
  185. for (var scanner = new Scanner(template2), start, type, value, chr, token, openSection; !scanner.eos(); ) {
  186. if (start = scanner.pos, value = scanner.scanUntil(openingTagRe), value)
  187. for (var i = 0, valueLength = value.length; i < valueLength; ++i)
  188. chr = value.charAt(i), isWhitespace(chr) ? (spaces.push(tokens.length), indentation += chr) : (nonSpace = !0, lineHasNonSpace = !0, indentation += " "), tokens.push(["text", chr, start, start + 1]), start += 1, chr === `
  189. ` && (stripSpace(), indentation = "", tagIndex = 0, lineHasNonSpace = !1);
  190. if (!scanner.scan(openingTagRe))
  191. break;
  192. if (hasTag = !0, type = scanner.scan(tagRe) || "name", scanner.scan(whiteRe), type === "=" ? (value = scanner.scanUntil(equalsRe), scanner.scan(equalsRe), scanner.scanUntil(closingTagRe)) : type === "{" ? (value = scanner.scanUntil(closingCurlyRe), scanner.scan(curlyRe), scanner.scanUntil(closingTagRe), type = "&") : value = scanner.scanUntil(closingTagRe), !scanner.scan(closingTagRe))
  193. throw new Error("Unclosed tag at " + scanner.pos);
  194. if (type == ">" ? token = [type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace] : token = [type, value, start, scanner.pos], tagIndex++, tokens.push(token), type === "#" || type === "^")
  195. sections.push(token);
  196. else if (type === "/") {
  197. if (openSection = sections.pop(), !openSection)
  198. throw new Error('Unopened section "' + value + '" at ' + start);
  199. if (openSection[1] !== value)
  200. throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
  201. } else
  202. type === "name" || type === "{" || type === "&" ? nonSpace = !0 : type === "=" && compileTags(value);
  203. }
  204. if (stripSpace(), openSection = sections.pop(), openSection)
  205. throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
  206. return nestTokens(squashTokens(tokens));
  207. }
  208. function squashTokens(tokens) {
  209. for (var squashedTokens = [], token, lastToken, i = 0, numTokens = tokens.length; i < numTokens; ++i)
  210. token = tokens[i], token && (token[0] === "text" && lastToken && lastToken[0] === "text" ? (lastToken[1] += token[1], lastToken[3] = token[3]) : (squashedTokens.push(token), lastToken = token));
  211. return squashedTokens;
  212. }
  213. function nestTokens(tokens) {
  214. for (var nestedTokens = [], collector = nestedTokens, sections = [], token, section, i = 0, numTokens = tokens.length; i < numTokens; ++i)
  215. switch (token = tokens[i], token[0]) {
  216. case "#":
  217. case "^":
  218. collector.push(token), sections.push(token), collector = token[4] = [];
  219. break;
  220. case "/":
  221. section = sections.pop(), section[5] = token[2], collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
  222. break;
  223. default:
  224. collector.push(token);
  225. }
  226. return nestedTokens;
  227. }
  228. function Scanner(string) {
  229. this.string = string, this.tail = string, this.pos = 0;
  230. }
  231. Scanner.prototype.eos = function() {
  232. return this.tail === "";
  233. };
  234. Scanner.prototype.scan = function(re) {
  235. var match = this.tail.match(re);
  236. if (!match || match.index !== 0)
  237. return "";
  238. var string = match[0];
  239. return this.tail = this.tail.substring(string.length), this.pos += string.length, string;
  240. };
  241. Scanner.prototype.scanUntil = function(re) {
  242. var index = this.tail.search(re), match;
  243. switch (index) {
  244. case -1:
  245. match = this.tail, this.tail = "";
  246. break;
  247. case 0:
  248. match = "";
  249. break;
  250. default:
  251. match = this.tail.substring(0, index), this.tail = this.tail.substring(index);
  252. }
  253. return this.pos += match.length, match;
  254. };
  255. function Context(view, parentContext) {
  256. this.view = view, this.cache = { ".": this.view }, this.parent = parentContext;
  257. }
  258. Context.prototype.push = function(view) {
  259. return new Context(view, this);
  260. };
  261. Context.prototype.lookup = function(name) {
  262. var cache = this.cache, value;
  263. if (cache.hasOwnProperty(name))
  264. value = cache[name];
  265. else {
  266. for (var context = this, intermediateValue, names, index, lookupHit = !1; context; ) {
  267. if (name.indexOf(".") > 0)
  268. for (intermediateValue = context.view, names = name.split("."), index = 0; intermediateValue != null && index < names.length; )
  269. index === names.length - 1 && (lookupHit = hasProperty(intermediateValue, names[index]) || primitiveHasOwnProperty(intermediateValue, names[index])), intermediateValue = intermediateValue[names[index++]];
  270. else
  271. intermediateValue = context.view[name], lookupHit = hasProperty(context.view, name);
  272. if (lookupHit) {
  273. value = intermediateValue;
  274. break;
  275. }
  276. context = context.parent;
  277. }
  278. cache[name] = value;
  279. }
  280. return isFunction(value) && (value = value.call(this.view)), value;
  281. };
  282. function Writer() {
  283. this.templateCache = {
  284. _cache: {},
  285. set: function(key, value) {
  286. this._cache[key] = value;
  287. },
  288. get: function(key) {
  289. return this._cache[key];
  290. },
  291. clear: function() {
  292. this._cache = {};
  293. }
  294. };
  295. }
  296. Writer.prototype.clearCache = function() {
  297. typeof this.templateCache != "undefined" && this.templateCache.clear();
  298. };
  299. Writer.prototype.parse = function(template2, tags) {
  300. var cache = this.templateCache, cacheKey = template2 + ":" + (tags || mustache.tags).join(":"), isCacheEnabled = typeof cache != "undefined", tokens = isCacheEnabled ? cache.get(cacheKey) : void 0;
  301. return tokens == null && (tokens = parseTemplate(template2, tags), isCacheEnabled && cache.set(cacheKey, tokens)), tokens;
  302. };
  303. Writer.prototype.render = function(template2, view, partials, config) {
  304. var tags = this.getConfigTags(config), tokens = this.parse(template2, tags), context = view instanceof Context ? view : new Context(view, void 0);
  305. return this.renderTokens(tokens, context, partials, template2, config);
  306. };
  307. Writer.prototype.renderTokens = function(tokens, context, partials, originalTemplate, config) {
  308. for (var buffer = "", token, symbol, value, i = 0, numTokens = tokens.length; i < numTokens; ++i)
  309. value = void 0, token = tokens[i], symbol = token[0], symbol === "#" ? value = this.renderSection(token, context, partials, originalTemplate, config) : symbol === "^" ? value = this.renderInverted(token, context, partials, originalTemplate, config) : symbol === ">" ? value = this.renderPartial(token, context, partials, config) : symbol === "&" ? value = this.unescapedValue(token, context) : symbol === "name" ? value = this.escapedValue(token, context, config) : symbol === "text" && (value = this.rawValue(token)), value !== void 0 && (buffer += value);
  310. return buffer;
  311. };
  312. Writer.prototype.renderSection = function(token, context, partials, originalTemplate, config) {
  313. var self = this, buffer = "", value = context.lookup(token[1]);
  314. function subRender(template2) {
  315. return self.render(template2, context, partials, config);
  316. }
  317. if (value) {
  318. if (isArray(value))
  319. for (var j = 0, valueLength = value.length; j < valueLength; ++j)
  320. buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config);
  321. else if (typeof value == "object" || typeof value == "string" || typeof value == "number")
  322. buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config);
  323. else if (isFunction(value)) {
  324. if (typeof originalTemplate != "string")
  325. throw new Error("Cannot use higher-order sections without the original template");
  326. value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender), value != null && (buffer += value);
  327. } else
  328. buffer += this.renderTokens(token[4], context, partials, originalTemplate, config);
  329. return buffer;
  330. }
  331. };
  332. Writer.prototype.renderInverted = function(token, context, partials, originalTemplate, config) {
  333. var value = context.lookup(token[1]);
  334. if (!value || isArray(value) && value.length === 0)
  335. return this.renderTokens(token[4], context, partials, originalTemplate, config);
  336. };
  337. Writer.prototype.indentPartial = function(partial, indentation, lineHasNonSpace) {
  338. for (var filteredIndentation = indentation.replace(/[^ \t]/g, ""), partialByNl = partial.split(`
  339. `), i = 0; i < partialByNl.length; i++)
  340. partialByNl[i].length && (i > 0 || !lineHasNonSpace) && (partialByNl[i] = filteredIndentation + partialByNl[i]);
  341. return partialByNl.join(`
  342. `);
  343. };
  344. Writer.prototype.renderPartial = function(token, context, partials, config) {
  345. if (partials) {
  346. var tags = this.getConfigTags(config), value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
  347. if (value != null) {
  348. var lineHasNonSpace = token[6], tagIndex = token[5], indentation = token[4], indentedValue = value;
  349. tagIndex == 0 && indentation && (indentedValue = this.indentPartial(value, indentation, lineHasNonSpace));
  350. var tokens = this.parse(indentedValue, tags);
  351. return this.renderTokens(tokens, context, partials, indentedValue, config);
  352. }
  353. }
  354. };
  355. Writer.prototype.unescapedValue = function(token, context) {
  356. var value = context.lookup(token[1]);
  357. if (value != null)
  358. return value;
  359. };
  360. Writer.prototype.escapedValue = function(token, context, config) {
  361. var escape = this.getConfigEscape(config) || mustache.escape, value = context.lookup(token[1]);
  362. if (value != null)
  363. return typeof value == "number" && escape === mustache.escape ? String(value) : escape(value);
  364. };
  365. Writer.prototype.rawValue = function(token) {
  366. return token[1];
  367. };
  368. Writer.prototype.getConfigTags = function(config) {
  369. return isArray(config) ? config : config && typeof config == "object" ? config.tags : void 0;
  370. };
  371. Writer.prototype.getConfigEscape = function(config) {
  372. if (config && typeof config == "object" && !isArray(config))
  373. return config.escape;
  374. };
  375. var mustache = {
  376. name: "mustache.js",
  377. version: "4.2.0",
  378. tags: ["{{", "}}"],
  379. clearCache: void 0,
  380. escape: void 0,
  381. parse: void 0,
  382. render: void 0,
  383. Scanner: void 0,
  384. Context: void 0,
  385. Writer: void 0,
  386. /**
  387. * Allows a user to override the default caching strategy, by providing an
  388. * object with set, get and clear methods. This can also be used to disable
  389. * the cache by setting it to the literal `undefined`.
  390. */
  391. set templateCache(cache) {
  392. defaultWriter.templateCache = cache;
  393. },
  394. /**
  395. * Gets the default or overridden caching object from the default writer.
  396. */
  397. get templateCache() {
  398. return defaultWriter.templateCache;
  399. }
  400. }, defaultWriter = new Writer();
  401. mustache.clearCache = function() {
  402. return defaultWriter.clearCache();
  403. };
  404. mustache.parse = function(template2, tags) {
  405. return defaultWriter.parse(template2, tags);
  406. };
  407. mustache.render = function(template2, view, partials, config) {
  408. if (typeof template2 != "string")
  409. throw new TypeError('Invalid template! Template should be a "string" but "' + typeStr(template2) + '" was given as the first argument for mustache#render(template, view, partials)');
  410. return defaultWriter.render(template2, view, partials, config);
  411. };
  412. mustache.escape = escapeHtml;
  413. mustache.Scanner = Scanner;
  414. mustache.Context = Context;
  415. mustache.Writer = Writer;
  416. var mustache_default = mustache;
  417.  
  418. // node_modules/.pnpm/delegate-it@5.0.0/node_modules/delegate-it/index.js
  419. var ledger = /* @__PURE__ */ new WeakMap();
  420. function editLedger(wanted, baseElement, callback, setup) {
  421. var _a, _b;
  422. if (!wanted && !ledger.has(baseElement))
  423. return !1;
  424. let elementMap = (_a = ledger.get(baseElement)) != null ? _a : /* @__PURE__ */ new WeakMap();
  425. if (ledger.set(baseElement, elementMap), !wanted && !ledger.has(baseElement))
  426. return !1;
  427. let setups = (_b = elementMap.get(callback)) != null ? _b : /* @__PURE__ */ new Set();
  428. elementMap.set(callback, setups);
  429. let existed = setups.has(setup);
  430. return wanted ? setups.add(setup) : setups.delete(setup), existed && wanted;
  431. }
  432. function isEventTarget(elements) {
  433. return typeof elements.addEventListener == "function";
  434. }
  435. function safeClosest(event, selector) {
  436. let target = event.target;
  437. if (target instanceof Text && (target = target.parentElement), target instanceof Element && event.currentTarget instanceof Element) {
  438. let closest = target.closest(selector);
  439. if (closest && event.currentTarget.contains(closest))
  440. return closest;
  441. }
  442. }
  443. function delegate(base, selector, type, callback, options) {
  444. let listenerOptions = typeof options == "object" ? options : { capture: options };
  445. delete listenerOptions.once;
  446. let { signal } = listenerOptions;
  447. if (signal != null && signal.aborted)
  448. return;
  449. if (typeof base == "string" && (base = document.querySelectorAll(base)), !isEventTarget(base)) {
  450. for (let element of base)
  451. delegate(element, selector, type, callback, listenerOptions);
  452. return;
  453. }
  454. let baseElement = base instanceof Document ? base.documentElement : base, capture = Boolean(typeof options == "object" ? options.capture : options), listenerFn = (event) => {
  455. let delegateTarget = safeClosest(event, selector);
  456. if (delegateTarget) {
  457. let delegateEvent = Object.assign(event, { delegateTarget });
  458. callback.call(baseElement, delegateEvent);
  459. }
  460. }, setup = JSON.stringify({ selector, type, capture });
  461. editLedger(!0, baseElement, callback, setup) || baseElement.addEventListener(type, listenerFn, listenerOptions), signal == null || signal.addEventListener("abort", () => {
  462. editLedger(!1, baseElement, callback, setup);
  463. });
  464. }
  465. var delegate_it_default = delegate;
  466.  
  467. // src/popup.ts
  468. var linkSelector = `a.${RJ_CODE_LINK_CLASS}`, template = `
  469. <img src="{{ image }}">
  470. <div class="info">
  471. <h3>{{ name }}</h3>
  472. {{ #rating }}<p><span>\u8BC4\u4EF7\uFF1A</span><span>{{ rating }}</span></p>{{ /rating }}
  473. {{ #sale }}<p><span>\u8D29\u5356\u6570\uFF1A</span><span>{{ sale }}</span></p>{{ /sale }}
  474. {{ #group }}<p><span>\u793E\u56E2\u540D\uFF1A</span><span>{{ group }}</span></p>{{ /group }}
  475. {{ #date }}<p><span>\u8D29\u5356\u65E5\uFF1A</span><span>{{ date }}</span></p>{{ /date }}
  476. {{ #series }}<p><span>\u7CFB\u5217\u540D\uFF1A</span><span>{{ series }}</span></p>{{ /series }}
  477. {{ #hasCreators }}<p><span>\u4F5C\u8005\uFF1A</span>{{ #creators }}<span>{{ . }} / </span>{{ /creators }}</p>{{ /hasCreators }}
  478. {{ #hasScenarios }}<p><span>\u5267\u60C5\uFF1A</span>{{ #scenarios }}<span>{{ . }} / </span>{{ /scenarios }}</p>{{ /hasScenarios }}
  479. {{ #hasIllusts }}<p><span>\u63D2\u753B\uFF1A</span>{{ #illusts }}<span>{{ . }} / </span>{{ /illusts }}</p>{{ /hasIllusts }}
  480. {{ #hasVoices }}<p><span>\u58F0\u4F18\uFF1A</span>{{ #voices }}<span>{{ . }} / </span>{{ /voices }}</p>{{ /hasVoices }}
  481. {{ #hasMusics }}<p><span>\u97F3\u4E50\uFF1A</span>{{ #musics }}<span>{{ . }} / </span>{{ /musics }}</p>{{ /hasMusics }}
  482. {{ #age }}<p><span>\u5E74\u9F84\u6307\u5B9A\uFF1A</span><span>{{ age }}</span></p>{{ /age }}
  483. {{ #type }}<p><span>\u4F5C\u54C1\u7C7B\u578B\uFF1A</span><span>{{ type }}</span></p>{{ /type }}
  484. {{ #hasTags }}<p><span>\u5206\u7C7B\uFF1A</span>{{ #tags }}<span>{{ . }} </span>{{ /tags }}</p>{{ /hasTags }}
  485. </div>`, currentWork, currentRj;
  486. async function show(x, y) {
  487. let popup = document.getElementById("rj-popup");
  488. if (currentWork = await fetch_rj_default(currentRj), console.debug("[rj-code-preview/work]", currentWork), !hided) {
  489. let rendered = mustache_default.render(template, currentWork, null, {
  490. escape: (it) => it
  491. });
  492. console.debug("[rj-code-preview/rendered]", rendered), popup.innerHTML = rendered, move(x, y);
  493. let img = popup.getElementsByTagName("img").item(0);
  494. img.onload = () => move(x, y), img.onerror = () => move(x, y);
  495. }
  496. hided = !1;
  497. }
  498. var hided = !1;
  499. function hide() {
  500. hided = !0, currentRj = void 0, currentWork = void 0, document.getElementById("rj-popup").innerHTML = "";
  501. }
  502. function move(x, y) {
  503. let popup = document.getElementById("rj-popup");
  504. popup.offsetWidth + x + 24 < window.innerWidth ? popup.style.left = x + 8 + "px" : popup.style.left = x - popup.offsetWidth - 8 + "px", popup.offsetHeight + y + 16 > window.innerHeight ? popup.style.top = window.innerHeight - popup.offsetHeight - 16 + "px" : popup.style.top = y + "px";
  505. }
  506. delegate_it_default(document.body, linkSelector, "mouseout", () => hide());
  507. delegate_it_default(document.body, linkSelector, "mouseover", async (event) => {
  508. currentRj = event.target.dataset[RJ_CODE_ATTRIBUTE], console.debug("[rj-code-preview/rj]", currentRj), currentRj && (hided = !1, await show(event.clientX, event.clientY));
  509. });
  510. delegate_it_default(
  511. document.body,
  512. linkSelector,
  513. "mousemove",
  514. (event) => move(event.clientX, event.clientY)
  515. );
  516. function initPopup() {
  517. GM_addElement(document.body, "div", { id: "rj-popup" });
  518. let style2 = document.createElement("style");
  519. style2.innerHTML = `
  520. #rj-popup {
  521. max-width: 360px;
  522. position: fixed;
  523. display: flex;
  524. flex-direction: column;
  525. overflow: hidden;
  526. color: #fff;
  527. background-color: #424242;
  528. border-radius: 12px;
  529. z-index: 99999;
  530. }
  531. #rj-popup > img {
  532. width: 100%;
  533. height: auto;
  534. border-radius: 0;
  535. }
  536. #rj-popup > .info {
  537. padding: 12px 16px;
  538. font-size: 0.88rem;
  539. line-height: 1.2;
  540. display: grid;
  541. grid-gap: 6px;
  542. box-sizing: border-box;
  543. }
  544. #rj-popup > .info > * {
  545. margin: 0;
  546. }
  547. #rj-popup > .info > h3 {
  548. font-size: 1.1rem;
  549. font-weight: bold;
  550. line-height: 1;
  551. }`, document.head.append(style2);
  552. }
  553.  
  554. // src/index.ts
  555. var observer = new MutationObserver((records) => {
  556. for (let { addedNodes } of records)
  557. for (let node of addedNodes)
  558. hack_rj_code_default(node);
  559. });
  560. observer.observe(document.body, { childList: !0, subtree: !0 });
  561. hack_rj_code_default(document.body);
  562. var style = document.createElement("style");
  563. style.innerHTML = `
  564. .${RJ_CODE_LINK_CLASS} {
  565. color: inherit;
  566. -webkit-text-stroke-width: 1px;
  567. }`;
  568. document.head.append(style);
  569. initPopup();
  570. document.addEventListener("securitypolicyviolation", (e) => {
  571. e.blockedURI.includes("img.dlsite.jp") && document.querySelector(`img[src="${e.blockedURI}"]`).remove();
  572. });
  573. /*! Bundled license information:
  574.  
  575. mustache/mustache.mjs:
  576. (*!
  577. * mustache.js - Logic-less {{mustache}} templates with JavaScript
  578. * http://github.com/janl/mustache.js
  579. *)
  580. */