Show full size image in m.facebook.com for firefox

Show full size image in m.facebook.com.

当前为 2021-02-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Show full size image in m.facebook.com for firefox
  3. // @namespace Show full size image in m.facebook.com for firefox
  4. // @include /https\:\/\/m\.facebook\.com\//
  5. // @version 3.7
  6. // @author zero0evolution
  7. // @description Show full size image in m.facebook.com.
  8. // ==/UserScript==
  9.  
  10.  
  11. // example site:"https://m.facebook.com/photo.php?fbid=...","https://m.facebook.com/.../photos/..."
  12.  
  13. // 圖片網頁格式
  14. // /^https\:\/\/m\.facebook\.com\/(?:[0-9a-zA-Z\.]+\/photos\/[0-9a-zA-Z\.]+\/\d+|photo\.php\?fbid\=\d+)/
  15.  
  16.  
  17. function unicodeToChar(text){
  18. text = text.replace(
  19. /\\u[\dA-F]{4}/gi,(match) => {
  20. // 刪掉\u
  21. match = match.replace(/\\u/g, '')
  22. // 16進位轉10進位
  23. match = parseInt(match, 16)
  24. // 轉字元
  25. match = String.fromCharCode(match)
  26. return(match)
  27. }
  28. )
  29. return(text)
  30. }
  31.  
  32. async function getHTML(link,encoding="UTF-8",
  33. requestOptions = {"credentials": "same-origin"}){
  34.  
  35. const response = await fetch(
  36. link,requestOptions
  37. ).then(
  38. (response)=>{return(response)}
  39. )
  40.  
  41. const arrayBuffer = await response.arrayBuffer().then(
  42. (arrayBuffer)=>{return(arrayBuffer)}
  43. )
  44.  
  45. const htmlCode = new TextDecoder(encoding).decode(arrayBuffer)
  46.  
  47. return(htmlCode)
  48. }
  49.  
  50. async function getOriginLink(link){
  51. const htmlCode = await getHTML(link)
  52. const matchImgLinkObj = htmlCode.match(/document\.location\.href\=\"(.*?)\"/)
  53. if(matchImgLinkObj){
  54. const originLink = matchImgLinkObj[1].replace(/\\\//img,"/")
  55. console.log("得到新的圖片連結:",originLink)
  56. return(originLink)
  57. }
  58. }
  59.  
  60. function loadImg(link){
  61. return(
  62. new Promise(
  63. (resolve,reject)=>{
  64. let tempImg
  65. if(typeof(link) === "string"){
  66. tempImg = document.createElement("img")
  67. tempImg.src = link
  68. }
  69. else if(link instanceof Element && link.matches("img")){
  70. tempImg = link
  71. }
  72. else{
  73. reject("no img link or img elem")
  74. }
  75. tempImg.onload = async(event)=>{
  76. resolve(tempImg)
  77. }
  78. }
  79. )
  80. )
  81. }
  82.  
  83. async function imgViewFullSize(targetImg,link){
  84. targetImg.style.maxWidth = "100%"
  85. // targetImg.style.maxHeight = "100vh"
  86. targetImg.style.height = "auto"
  87. targetImg.style.width = "auto"
  88.  
  89. targetImg.removeAttribute("width")
  90. targetImg.removeAttribute("height")
  91.  
  92. let elem = targetImg.parentElement
  93.  
  94. while(elem.style.width || elem.style.height){
  95.  
  96. elem.style.removeProperty("width")
  97. elem.style.removeProperty("height")
  98.  
  99. const elemStyle = getComputedStyle(elem)
  100. if(elemStyle.position.match(/^(absolute|fixed)$/)){
  101. elem.style.position = "static"
  102. }
  103. elem = elem.parentElement
  104. }
  105.  
  106. // check if link is not png,jpg, need redirect
  107. if(!link.match(/.*\/(.*?\.(?:png|jpg))(?:\?.*)?$/)){
  108. link = await getOriginLink(link)
  109. }
  110.  
  111. if(targetImg.matches("img")){
  112.  
  113. await loadImg(link)
  114.  
  115. targetImg.src = link
  116. return(targetImg)
  117. }
  118. else if(targetImg.matches("i.img")){
  119. const parent = targetImg.parentElement
  120.  
  121. targetImg.remove()
  122. const tempElem = document.createElement("div")
  123. tempElem.innerHTML = `<img src=${link} style="max-width:100%">`
  124. const newTargetImg = tempElem.firstElementChild
  125. parent.appendChild(newTargetImg)
  126. await loadImg(newTargetImg)
  127. return(newTargetImg)
  128. }
  129.  
  130. }
  131.  
  132. function replaceLinkElem(linkElem){
  133. const newElem = document.createElement("span")
  134. newElem.dataset.link = linkElem.href
  135. newElem.textContent = linkElem.textContent
  136. linkElem.parentElement.insertBefore(newElem,linkElem)
  137. linkElem.remove()
  138. return(newElem)
  139. }
  140.  
  141. function moveElemFunc(moveElem,targetElem){
  142. if(targetElem.parentElement instanceof Element){
  143. targetElem.parentElement.insertBefore(moveElem,targetElem.nextSibling)
  144. return(moveElem)
  145. }
  146. }
  147.  
  148. function moveElemsFunc(moveElems,targetElem){
  149. for(let i=moveElems.length-1;i>=0;i--){
  150. moveElemFunc(moveElems[i],targetElem)
  151. }
  152. }
  153.  
  154.  
  155. async function showFullFunc(linkElem){
  156.  
  157. const originHref = linkElem.getAttribute("href")
  158.  
  159. if(!originHref){
  160. // console.warn(linkElem)
  161. return(null)
  162. }
  163.  
  164. const viewFullSizeTextPattern = /^(?:全尺寸檢視|view full size)$/i
  165.  
  166. if(
  167. linkElem.textContent.match(viewFullSizeTextPattern) &&
  168. linkElem.matches("#viewport #rootcontainer a[href]")
  169. ){
  170.  
  171. let targetElem = document.querySelector("#viewport #rootcontainer i.img[role='img'][data-store][style^='background-image: url']")
  172. if(targetElem instanceof Element){
  173. // const parent = targetElem.parentElement
  174.  
  175. // const tempElem = document.createElement("div")
  176. // tempElem.innerHTML = `<img src=${linkElem.href} style="max-width:100%">`
  177. // parent.appendChild(tempElem.firstElementChild)
  178. // targetElem.remove()
  179.  
  180. targetElem = await imgViewFullSize(targetElem,linkElem.getAttribute("href"))
  181. }
  182. }
  183.  
  184. const photoLinkPattern = /^\/?(?:photo\.php\?fbid\=|[0-9a-z\.\-\_]+\/photos\/)/i
  185. const photoLinkPattern2 = /^\/[0-9a-zA-Z\.]+\/photos\/[0-9a-zA-Z\.]+\/[0-9]+/i
  186.  
  187. const photoLinkPattern3 = /^\/photos\/viewer\/\?/
  188.  
  189. if(
  190. originHref.match(photoLinkPattern) ||
  191. originHref.match(photoLinkPattern2) ||
  192. originHref.match(photoLinkPattern3)
  193. ){
  194.  
  195. let targetImg = linkElem.querySelector(
  196. "i.img[role='img'][style*='background-image:']")
  197. if(targetImg instanceof Element){
  198.  
  199. // console.log(linkElem.href)
  200.  
  201. linkElem.parentElement.align = "center"
  202. linkElem.parentElement.style.width = "100%"
  203. linkElem.parentElement.style.removeProperty("height")
  204. linkElem.parentElement.style.display = "inline-block"
  205. linkElem.style.removeProperty("left")
  206. linkElem.style.removeProperty("top")
  207. linkElem.style.removeProperty("width")
  208. linkElem.style.removeProperty("height")
  209. linkElem.style.maxWidth = "100%"
  210. linkElem.style.height = "auto"
  211. linkElem.style.position = "relative"
  212.  
  213. let nextLinkElem = linkElem.nextElementSibling
  214.  
  215. const htmlCode = await getHTML(linkElem.href)
  216. const matches = htmlCode.match(/\<a\s.*?\<\/a\>/img)
  217. // console.log(matches)
  218. for(const match of matches){
  219. const tempElem = document.createElement("div")
  220. tempElem.innerHTML = match
  221. const fullSizeLinkElem = tempElem.firstElementChild
  222. if(fullSizeLinkElem.textContent.match(viewFullSizeTextPattern)){
  223.  
  224. let fullImgLink = fullSizeLinkElem.getAttribute("href")
  225. if(!fullImgLink.match(/.*\/(.*?\.(?:png|jpg))(?:\?.*)?$/)){
  226. fullImgLink = await getOriginLink(fullImgLink)
  227. }
  228. linkElem.innerHTML = `<img src="${fullImgLink}" style="max-width:100%;height:auto;">`
  229. // console.log(linkElem.innerHTML)
  230. // targetImg = await imgViewFullSize(targetImg,fullSizeLinkElem.href)
  231.  
  232. linkElem.parentElement.insertBefore(document.createElement("br"),linkElem.nextElementSibling)
  233. break
  234. }
  235. }
  236.  
  237.  
  238. if(
  239. (!(nextLinkElem instanceof Element)) ||
  240. (!(nextLinkElem.matches("a[href]")))
  241. ){
  242. // console.log("最後一個linkElem:",linkElem)
  243. // 找下一張連結
  244. for(const match of matches){
  245. const tempElem = document.createElement("div")
  246. tempElem.innerHTML = match
  247. nextLinkElem = tempElem.firstElementChild
  248. if(!nextLinkElem.matches("a.touchable[href]")){
  249. continue
  250. }
  251. if(!nextLinkElem.textContent.match(/^(Next|繼續)$/i)){
  252. continue
  253. }
  254. const nextLink = nextLinkElem.getAttribute("href")
  255. // 建立按鈕且功能為加入下一張圖片
  256. const button = document.createElement("button")
  257. button.textContent = "Next"
  258. linkElem.parentElement.insertBefore(button,linkElem.nextElementSibling.nextElementSibling)
  259.  
  260. button.dataset.link = nextLink
  261.  
  262. button.addEventListener("click",function(event){
  263. const button = event.currentTarget
  264. const link = button.dataset.link
  265. const tempElem = document.createElement("div")
  266. tempElem.innerHTML = `
  267. <a href="${link}">
  268. <i class="img" role="img" style="background-image:none;"></i>
  269. </a>
  270. `
  271. const nextLinkElem = tempElem.firstElementChild
  272.  
  273. button.parentElement.insertBefore(
  274. nextLinkElem,button.nextElementSibling)
  275.  
  276. button.remove()
  277. })
  278. }
  279. }
  280. }
  281. }
  282.  
  283. // 新增影片
  284. const videoLinkPattern = /^\/?video\_redirect\/\?src\=/i
  285. if(originHref.match(videoLinkPattern)){
  286. const videoLink = decodeURIComponent(originHref.replace(videoLinkPattern,""))
  287. const videoElem = document.createElement("video")
  288. videoElem.src = videoLink
  289. videoElem.controls = true
  290. // videoElem.style.maxWidth = "100%"
  291. videoElem.style.width = "100%"
  292. videoElem.style.minHeight = "60vh"
  293. videoElem.style.maxHeight = "100vh"
  294.  
  295. linkElem.parentElement.insertBefore(videoElem,linkElem.nextSibling)
  296. linkElem.remove()
  297. // videoElem.parentElement.align = "center"
  298. }
  299. }
  300.  
  301.  
  302. // 挑出所有的連結
  303. // const selectorText = "a[href]"
  304. async function filterFunc(topElem){
  305. if(topElem.matches("a[href]")){
  306. await showFullFunc(topElem).catch((err)=>{console.warn(err)})
  307. }
  308. for(const linkElem of topElem.querySelectorAll("a[href]")){
  309. await showFullFunc(linkElem).catch((err)=>{console.warn(err)})
  310. }
  311. }
  312.  
  313. filterFunc(document.documentElement)
  314.  
  315. const observerObj = new MutationObserver(
  316. function (mutationObjs){
  317. for(const eachMutationObj of mutationObjs){
  318. for(const eachAddNode of eachMutationObj.addedNodes){
  319. if(eachAddNode.nodeType === 1){
  320. filterFunc(eachAddNode)
  321. }
  322. }
  323. }
  324. }
  325. )
  326.  
  327. observerObj.observe(
  328. document.documentElement,{
  329. childList:true,
  330. subtree:true,
  331. }
  332. )
  333.  
  334.  
  335. // 顯示更多
  336. // 查看更多動態
  337. // video