Copy Link Common Library

Copy Link for Common Library

目前为 2022-09-18 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/451573/1095110/Copy%20Link%20Common%20Library.js

  1. function updateClipboard(CopyData) {
  2. try {
  3. navigator.clipboard.writeText(CopyData).then(function() {
  4. console.log('navigator.clipboard - Copying to clipboard was successful!')
  5. })
  6. } catch {
  7. GM_setClipboard(CopyData)
  8. console.log('GM_setClipboard - Copying to clipboard was successful!')
  9. }
  10. }
  11.  
  12. function MaxZIndexFromPoint(selector) {
  13. //console.log(selector, getAllElementsFromPoint(document.querySelector(selector)) + 1)
  14. return getAllElementsFromPoint(document.querySelector(selector))
  15. }
  16.  
  17. function getMaxZIndex() {
  18. return Math.max(
  19. ...Array.from(document.querySelectorAll('body *'), el =>
  20. parseFloat(window.getComputedStyle(el).zIndex),
  21. ).filter(zIndex => !Number.isNaN(zIndex)),
  22. 1,
  23. );
  24. }
  25.  
  26. function getZIndex(el) {
  27. if (el && el !== document.body && el !== window && el !== document && el !== document.documentElement) {
  28. var z = window.document.defaultView.getComputedStyle(el).getPropertyValue('z-index');
  29. if (isNaN(z)) return getZIndex(el.parentNode);
  30. }
  31. return z;
  32. };
  33.  
  34. function getPosition(element) {
  35. let rect = element.getBoundingClientRect()
  36. return {
  37. x: rect.x,
  38. y: rect.y
  39. };
  40. }
  41.  
  42. function getAllElementsFromPoint(el) {
  43. let elements = [];
  44. let display = [];
  45. let zIndex = []
  46. let item = document.elementFromPoint(getPosition(el).x, getPosition(el).y)
  47. while (item && item !== document.body && item !== window && item !== document && item !== document.documentElement && el !== item) {
  48. //console.log(item)
  49. elements.push(item);
  50. display.push(item.style.display)
  51. if (!isNaN(getZIndex(item))) {
  52. let zI = getZIndex(item)
  53. console.log(zI)
  54. zIndex.push(zI)
  55. }
  56. item.style.display = "none";
  57. item = document.elementFromPoint(getPosition(el).x, getPosition(el).y);
  58. }
  59. // restore display property
  60. for (let i = 0; i < elements.length; i++) {
  61. elements[i].style.display = display[i];
  62. }
  63. return Math.max(...zIndex, 1);
  64. }
  65.  
  66. function getElementOffset(el) {
  67. let rect = el.getBoundingClientRect()
  68. return {
  69. top: rect.top,
  70. bottom: rect.bottom,
  71. left: rect.left,
  72. right: rect.right,
  73. width: rect.width,
  74. height: rect.height,
  75. };
  76. }
  77.  
  78. function getRelativeOffset(el) {
  79. return {
  80. top: el.offsetTop,
  81. bottom: el.offsetTop + el.offsetHeight,
  82. left: el.offsetLeft,
  83. right: el.offsetLeft + el.offsetWidth,
  84. width: el.offsetWidth,
  85. height: el.offsetHeight,
  86. };
  87. }
  88.  
  89. function getNodeTextElementOffset(node) {
  90. let textNode = getTextNodesIn(node, false)
  91. let range = document.createRange();
  92. try {
  93. range.selectNode(textNode);
  94. let rect = range.getBoundingClientRect()
  95. return {
  96. top: rect.top,
  97. bottom: rect.bottom,
  98. left: rect.left,
  99. right: rect.right,
  100. width: rect.width,
  101. height: rect.height,
  102. }
  103. } catch (error) {
  104. console.error(error)
  105. return {
  106. top: 0,
  107. bottom: 0,
  108. left: 0,
  109. right: 0,
  110. width: 0,
  111. height: 0,
  112. }
  113. }
  114. }
  115.  
  116. function getTextNodesIn(node, includeWhitespaceNodes) {
  117. var textNodes = [], nonWhitespaceMatcher = /\S/;
  118.  
  119. function getTextNodes(node) {
  120. if (node.nodeType == Node.TEXT_NODE) {
  121. if (includeWhitespaceNodes || nonWhitespaceMatcher.test(node.nodeValue)) {
  122. textNodes.push(node);
  123. }
  124. } else {
  125. for (var i = 0, len = node.childNodes.length; i < len; ++i) {
  126. getTextNodes(node.childNodes[i]);
  127. }
  128. }
  129. }
  130.  
  131. getTextNodes(node);
  132. //console.log(textNodes, textNodes?.length)
  133. return textNodes?.length ? textNodes.shift() : null;
  134. }
  135. function getDefaultFontSize() {
  136. const element = document.createElement('div');
  137. element.style.width = '1rem';
  138. element.style.display = 'none';
  139. document.body.append(element);
  140.  
  141. const widthMatch = window
  142. .getComputedStyle(element)
  143. .getPropertyValue('width')
  144. .match(/\d+/);
  145.  
  146. element.remove();
  147.  
  148. if (!widthMatch || widthMatch.length < 1) {
  149. return null;
  150. }
  151.  
  152. const result = Number(widthMatch[0]);
  153. return !isNaN(result) ? result : null;
  154. }
  155.  
  156. //백그라운드 이미지 가져오기
  157. function GetBackGroundUrl(Area) {
  158. let BackGroundUrl = ''
  159. try {
  160. let imgURL = window.document.defaultView.getComputedStyle(Area, null).getPropertyValue('background')
  161. BackGroundUrl = imgURL.replace(/.*\s?url\([\'\"]?/, '').replace(/[\'\"]?\).*/, '')
  162. return BackGroundUrl
  163. } catch (err) {
  164. console.log(err)
  165. }
  166. }
  167.  
  168. //Match
  169. function MatchRegex(Area, regex, attributeToSearch) {
  170. //console.log(Area, regex, attributeToSearch)
  171. const output = [];
  172. if (attributeToSearch) {
  173. for (let element of Area.querySelectorAll(`[${attributeToSearch}]`)) {
  174. //console.log(regex.test(element.getAttribute(attributeToSearch)), element)
  175. if (regex.test(element.getAttribute(attributeToSearch))) {
  176. //console.log(element)
  177. output.push(element);
  178. }
  179. }
  180. } else {
  181. for (let element of Area.querySelectorAll('*')) {
  182. for (let attribute of element.attributes) {
  183. if (regex.test(attribute.value)) {
  184. //console.log(element)
  185. output.push(element);
  186. }
  187. }
  188. }
  189. }
  190. return output;
  191. }
  192.  
  193. // Not Match
  194. function NotMatchRegex(Area, regex, attributeToSearch) {
  195. const output = [];
  196. if (attributeToSearch) {
  197. for (let element of Area.querySelectorAll(`[${attributeToSearch}]`)) {
  198. if (!regex.test(element.getAttribute(attributeToSearch))) {
  199. //console.log(element)
  200. output.push(element);
  201. }
  202. }
  203. } else {
  204. for (let element of Area.querySelectorAll('*')) {
  205. for (let attribute of element.attributes) {
  206. if (!regex.test(attribute.value)) {
  207. //console.log(element)
  208. output.push(element);
  209. }
  210. }
  211. }
  212. }
  213. return output;
  214. }
  215.  
  216. function querySelectorAllRegex(Area, regex, attributeToSearch) {
  217. const output = [];
  218. if (attributeToSearch === 'href') {
  219. for (let element of Area.querySelectorAll('A')) {
  220. if (element.href && !regex.test(element.href)) {
  221. //console.log(element, regex)
  222. output.push(element);
  223. }
  224. }
  225. } else if (attributeToSearch) {
  226. for (let element of Area.querySelectorAll(`[${attributeToSearch}]`)) {
  227. if (!regex.test(element.getAttribute(attributeToSearch))) {
  228. console.log(element, regex)
  229. output.push(element);
  230. }
  231. }
  232. } else {
  233. for (let element of Area.querySelectorAll('*')) {
  234. for (let attribute of element.attributes) {
  235. if (!regex.test(attribute.value)) {
  236. console.log(element)
  237. output.push(element);
  238. }
  239. }
  240. }
  241. }
  242. return output;
  243. }
  244.  
  245. function byteLengthOf(TitleText, maxByte) {
  246. //assuming the String is UCS-2(aka UTF-16) encoded
  247. let Result
  248. let CharByte = 0
  249. let LineByte = 0
  250. for (var i = 0, l = TitleText.length; i < l; i++) {
  251. var Code = TitleText.charCodeAt(i);
  252. if (Code < 0x0080) { //[0x0000, 0x007F]
  253. CharByte = 1
  254. LineByte += 1;
  255. } else if (Code < 0x0800) { //[0x0080, 0x07FF]
  256. CharByte = 2
  257. LineByte += 2;
  258. } else if (Code < 0xD800) { //[0x0800, 0xD7FF]
  259. CharByte = 3
  260. LineByte += 3;
  261. } else if (Code < 0xDC00) { //[0xD800, 0xDBFF]
  262. var lo = TitleText.charCodeAt(++i);
  263. if (i < l && lo >= 0xDC00 && lo <= 0xDFFF) { //followed by [0xDC00, 0xDFFF]
  264. CharByte = 4
  265. LineByte += 4;
  266. } else {
  267. CharByte = 0
  268. throw new Error("UCS-2 String malformed");
  269. }
  270. } else if (Code < 0xE000) { //[0xDC00, 0xDFFF]
  271. CharByte = 0
  272. throw new Error("UCS-2 String malformed");
  273. } else { //[0xE000, 0xFFFF]
  274. CharByte = 3
  275. LineByte += 3;
  276. }
  277. //console.log(TitleText[i], CharByte, LineByte)
  278. if (LineByte >= maxByte) {
  279. TitleText = TitleText.substr(0, i).replace(/(、|,)$/, '').trim()
  280. Result = TitleText + '…'
  281. break;
  282. }
  283. }
  284. return Result ? Result.trim() : TitleText
  285. }
  286.  
  287. function byteLengthOfCheck(TitleText) {
  288. if (typeof TitleText === 'undefined') { return 0 }
  289. //assuming the String is UCS-2(aka UTF-16) encoded
  290. let LineByte = 0
  291. for (var i = 0, l = TitleText.length; i < l; i++) {
  292. var Code = TitleText.charCodeAt(i);
  293. if (Code < 0x0080) { //[0x0000, 0x007F]
  294. LineByte += 1;
  295. } else if (Code < 0x0800) { //[0x0080, 0x07FF]
  296. LineByte += 2;
  297. } else if (Code < 0xD800) { //[0x0800, 0xD7FF]
  298. LineByte += 3;
  299. } else if (Code < 0xDC00) { //[0xD800, 0xDBFF]
  300. var lo = TitleText.charCodeAt(++i);
  301. if (i < l && lo >= 0xDC00 && lo <= 0xDFFF) { //followed by [0xDC00, 0xDFFF]
  302. LineByte += 4;
  303. } else {
  304. throw new Error("UCS-2 String malformed");
  305. }
  306. } else if (Code < 0xE000) { //[0xDC00, 0xDFFF]
  307. throw new Error("UCS-2 String malformed");
  308. } else { //[0xE000, 0xFFFF]
  309. LineByte += 3;
  310. }
  311. }
  312. return LineByte
  313. }
  314.  
  315. function SearchChar(Text, Char) {
  316. let result = ''
  317. let SearchEx = new RegExp(Char, 'g')
  318. if (Text.match(SearchEx)) {
  319. return Text.match(SearchEx).reverse()[0]
  320. } else return result
  321. }
  322.  
  323. function getFlag(Text) {
  324. let Point = []
  325. let LastPoint = Text.length - 1
  326. for (let j = LastPoint; j > 0; j--) {
  327. let Code = Text.charCodeAt(j)
  328. if (Code > 65280 && Code < 65375 && Code != 65306) {
  329. console.log(j, Code, String.fromCodePoint(Code))
  330. Point.push(j + 1)
  331. }
  332. }
  333. return Point
  334. }
  335.  
  336. //ingnore childNodes Text
  337. function ingnoreChildNodesText(element) {
  338. let childNodes = element.childNodes;
  339. result = '';
  340.  
  341. for (let i = 0; i < childNodes.length; i++) {
  342. if (childNodes[i].nodeType == 3) {
  343. result += childNodes[i].data;
  344. }
  345. }
  346.  
  347. return result;
  348. }
  349.  
  350. // innerText except A tag
  351. function getDirectInnerText(element) {
  352. let childNodes = element.childNodes;
  353. let result = ''
  354.  
  355. for (let i = 0; i < childNodes.length; i++) {
  356. //console.log('nodeType: ', childNodes[i], childNodes[i].nodeType, childNodes[i].tagName )
  357. if (childNodes[i].tagName === 'A' || childNodes[i].nodeType == 3) {
  358. result += childNodes[i].data ? childNodes[i].data : childNodes[i].textContent;
  359. }
  360. }
  361.  
  362. return result;
  363. }
  364.  
  365. //첫글자 대문자
  366. function nameCorrection(str) {
  367. let strPerfect = str.replace(/\s+/g, " ").trim();
  368. let strSmall = strPerfect.toLowerCase();
  369. let arrSmall = strSmall.split(" ");
  370. let arrCapital = [];
  371. for (let x of arrSmall.values()) {
  372. arrCapital.push(x[0].toUpperCase() + x.slice(1));
  373. }
  374.  
  375. return arrCapital.join(" ");
  376. }
  377.  
  378. function capitalize(str) {
  379. //console.log('capitalize: ', str)
  380. let result = str[0].toUpperCase();
  381.  
  382. for (let i = 1; i < str.length; i++) {
  383. if (str[i - 1] === ' ') {
  384. result += str[i].toUpperCase();
  385. } else {
  386. result += str[i];
  387. }
  388. }
  389.  
  390. return result;
  391. }
  392.  
  393. //파일명 사용불가 문자 전각문자로 변환
  394. function FilenameConvert(text) {
  395. const ExcludeChar = /[<\/:>*?"|\\]/g
  396. let result = text.replace(ExcludeChar, function(elem) {
  397. return String.fromCharCode(parseInt(elem.charCodeAt(0)) + 65248)
  398. })
  399. return result
  400. }
  401.  
  402. function getNumericMonth(monthAbbr) {
  403. monthAbbr = capitalize(monthAbbr)
  404. return (String(['January',
  405. 'February',
  406. 'March',
  407. 'April',
  408. 'May',
  409. 'June',
  410. 'July',
  411. 'August',
  412. 'September',
  413. 'October',
  414. 'November',
  415. 'December'
  416. ].indexOf(monthAbbr) + 1).padStart(2, '0'))
  417. }
  418.  
  419. /**
  420. * 해당 함수는
  421. * php의 mb_convert_kana의 Javascript 버전이다.
  422. * 히라가나는 반각이 없음.
  423. */
  424.  
  425. function mbConvertKana(text, option) {
  426. let katahan, kanazen, hirazen, mojilength, i, re;
  427. katahan = ["ガ", "ギ", "グ", "ゲ", "ゴ", "ザ", "ジ", "ズ", "ゼ", "ゾ", "ダ", "ヂ", "ヅ", "デ", "ド", "バ", "パ", "ビ", "ピ", "ブ", "プ", "ベ", "ペ", "ボ", "ポ", "ヴ", "ー", "ァ", "ア", "ィ", "イ", "ゥ", "ウ", "ェ", "エ", "ォ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ッ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヲ", "ン", "カ", "ケ", "ワ", "イ", "エ", "゙", "゚"];
  428. kanazen = ["ガ", "ギ", "グ", "ゲ", "ゴ", "ザ", "ジ", "ズ", "ゼ", "ゾ", "ダ", "ヂ", "ヅ", "デ", "ド", "バ", "パ", "ビ", "ピ", "ブ", "プ", "ベ", "ペ", "ボ", "ポ", "ヴ", "ー", "ァ", "ア", "ィ", "イ", "ゥ", "ウ", "ェ", "エ", "ォ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ッ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヲ", "ン", "ヵ", "ヶ", "ヮ", "ヰ", "ヱ", "゛", "゜"];
  429. hirazen = ["が", "ぎ", "ぐ", "げ", "ご", "ざ", "じ", "ず", "ぜ", "ぞ", "だ", "ぢ", "づ", "で", "ど", "ば", "ぱ", "び", "ぴ", "ぶ", "ぷ", "べ", "ぺ", "ぼ", "ぽ", "ヴ", "ー", "ぁ", "あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "っ", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "ゃ", "や", "ゅ", "ゆ", "ょ", "よ", "ら", "り", "る", "れ", "ろ", "わ", "を", "ん", "か", "け", "ゎ", "ゐ", "ゑ", "゛", "゜"];
  430. mojilength = katahan.length;
  431. // r: 전각문자를 반각으로 변환
  432. // a: 전각영문자를 반각으로 변환
  433. if (option.match(/[ra]/)) {
  434. text = text.replace(/[A-z]/g, function(elem) {
  435. return String.fromCharCode(parseInt(elem.charCodeAt(0)) - 65248);
  436. });
  437. }
  438. // R: 반각문자를 전각으로 변환
  439. // A: 반각영문자를 전각으로 변환
  440. if (option.match(/[RA]/)) {
  441. text = text.replace(/[A-z]/g, function(elem) {
  442. return String.fromCharCode(parseInt(elem.charCodeAt(0)) + 65248);
  443. });
  444. }
  445. // n: 전각숫자를 반각으로 변환
  446. // a: 전각 영숫자를 반각으로 변환
  447. if (option.match(/[na]/)) {
  448. text = text.replace(/[0-9]/g, function(elem) {
  449. return String.fromCharCode(parseInt(elem.charCodeAt(0)) - 65248);
  450. });
  451. }
  452. // N: 반각숫자를 전각으로 변환
  453. // A: 반각영숫자를 전각으로 변환
  454. if (option.match(/[NA]/)) {
  455. text = text.replace(/[0-9]/g, function(elem) {
  456. return String.fromCharCode(parseInt(elem.charCodeAt(0)) + 65248);
  457. });
  458. }
  459. // s: 전각스페이스를 반각으로 변환
  460. if (option.match(/s/)) {
  461. text = text.replace(/ /g, " ");
  462. }
  463. // S: 반각스페이스를 전각으로 변환
  464. if (option.match(/S/)) {
  465. text = text.replace(/ /g, " ");
  466. }
  467. // k: 전각카타카나를 반각 카타카타로 변환
  468. if (option.match(/k/)) {
  469. for (i = 0; i < mojilength; i++) {
  470. re = new RegExp(kanazen[i], "g");
  471. text = text.replace(re, katahan[i]);
  472. }
  473. }
  474. // K: 반각카타카타를 전각카타카타로 변환
  475. // V: 탁점사용중인 문자를 글자로 변환
  476. if (option.match(/K/)) {
  477. if (!option.match(/V/)) {
  478. text = text.replace(/゙/g, "゛");
  479. text = text.replace(/゚/g, "゜");
  480. }
  481. for (i = 0; i < mojilength; i++) {
  482. re = new RegExp(katahan[i], "g");
  483. text = text.replace(re, kanazen[i]);
  484. }
  485. }
  486. // h: 전각히라가나를 반각카타카나로 변환
  487. if (option.match(/h/)) {
  488. for (i = 0; i < mojilength; i++) {
  489. re = new RegExp(hirazen[i], "g");
  490. text = text.replace(re, katahan[i]);
  491. }
  492. }
  493. // H: 반각카타카나를 전각히라가라로 변환
  494. // V: 탁점사용중인 문자를 글자로 변환
  495. if (option.match(/H/)) {
  496. if (!option.match(/V/)) {
  497. text = text.replace(/゙/g, "゛");
  498. text = text.replace(/゚/g, "゜");
  499. }
  500. for (i = 0; i < mojilength; i++) {
  501. re = new RegExp(katahan[i], "g");
  502. text = text.replace(re, hirazen[i]);
  503. }
  504. }
  505. // c: 전각카타카나를 전각히라가나로 변환
  506. if (option.match(/c/)) {
  507. for (i = 0; i < mojilength; i++) {
  508. re = new RegExp(kanazen[i], "g");
  509. text = text.replace(re, hirazen[i]);
  510. }
  511. }
  512. // C: 전각히라가나를 전각카타카나로 변환
  513. if (option.match(/C/)) {
  514. for (i = 0; i < mojilength; i++) {
  515. re = new RegExp(hirazen[i], "g");
  516. text = text.replace(re, kanazen[i]);
  517. }
  518. }
  519. return text;
  520. }