Greasy Fork

Greasy Fork is available in English.

Workflowy 图片视频播客预览 Image Preview, Embed & Extend

Add image preview, embed videos & extend Workflowy

当前为 2023-09-16 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Workflowy 图片视频播客预览 Image Preview, Embed & Extend
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  Add image preview, embed videos & extend Workflowy
// @author       Namkit
// @match        https://workflowy.com/*
// @grant        none
// @require      http://libs.baidu.com/jquery/2.1.3/jquery.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/layer/3.5.1/layer.js
// @license      GNU GPLv3
// ==/UserScript==

;(function () {
  'use strict'

  const embedConfigs = [
    {
      name: 'xiaoyuzhou',
      regex: /www\.xiaoyuzhoufm\.com/,
      embedUrl: '$&', // 使用原始链接作为 embedUrl
    },
    {
      name: 'bilibili',
      regex: [
        /https?:\/\/(www\.)?bilibili\.com\/video\/(BV[\w]+)\//i,
        /https?:\/\/(b23\.)?tv\/(BV[\w]+)/i,
        /https?:\/\/(www\.)?bilibili\.com\/video\/(av[\d]+)\//i,
      ],
      embedUrl: '//player.bilibili.com/player.html?bvid=$2&high_quality=1&autoplay=0',
    },
  ]

  const imageRegex =
    /(https?:\/\/[^\s]+?(?:\.(?:jpg|jpeg|png|gif|svg|webp))|(?:.+&)?f=(?:JPEG|PNG|GIF|SVG|WEBP)|[^\s]+mmbiz_png.+wx_fmt=(?:JPEG|PNG|GIF|SVG|WEBP)|[^\s]+webp|\/[^\s]+?\.(?:jpg|jpeg|png|gif|svg|webp)|[^\s]+?\.(?:jpg|jpeg|png|gif|svg|webp)|[^\s]+\/photo\/[^\s]+|[^\s]+\/media\/[^\s]+)/i

  $(document.body).append(
    '<link href="https://cdn.bootcdn.net/ajax/libs/layer/3.5.1/theme/default/layer.min.css" rel="stylesheet">',
  )

  function createImagePreview(linkElem, imageUrl) {
    insertAfter(linkElem, document.createElement('br'))

    const container = document.createElement('div')
    container.id = 'id' + Math.random().toString().replace('.', '')
    container.style.cssText = `
      height: 60vh;
      display: flex;
      justify-content: left;
      align-items: center;
      margin-top: 8px;
      opacity: 1;
    `

    const previewImage = document.createElement('img')
    previewImage.src = imageUrl
    previewImage.style.cssText = `
      max-width: 100%;
      max-height: 100%;
      height: fit-content;
      object-fit: contain;
      object-position: center;
    `
    // 点击图片预览
    previewImage.addEventListener('click', (e) => {
       // 使用Layer.js显示预览图像
      // layer弹层组件开发文档 - Layui https://www.layuiweb.com/doc/modules/layer.html#shadeClose
      layer.photos({
        photos: '#' + e.target.parentNode.id,
        tab: () => {
          window.onmousewheel = document.onmousewheel = function (e) {
            var imagep = $('.layui-layer-phimg').parent().parent()
            var image = $('.layui-layer-phimg').parent()
            var h = image.height()
            var w = image.width()
            if (e.wheelDelta < 0) {
              //鼠标下滑事件
              if (h > 100) {
                h = h * 0.95
                w = w * 0.95
              }
            }
            if (e.wheelDelta > 0) {
              //鼠标上滑事件
              if (h < window.innerHeight) {
                h = h * 1.05
                w = w * 1.05
              }
            }
            imagep.css('top', (window.innerHeight - h) / 2)
            imagep.css('left', (window.innerWidth - w) / 2)
            image.height(h)
            image.width(w)
            imagep.height(h)
            imagep.width(w)
          }
        },
      })
    })

    container.appendChild(previewImage)
    insertAfter(linkElem, container)

    return previewImage
  }
  // 插入元素
  function insertAfter(referenceNode, newNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling)
  }
  // 创建 iframe
  function appendEmbedIframe(linkElem, embedUrl, width = 560, height = 315) {
    const iframe = document.createElement('iframe')
    iframe.src = embedUrl
    iframe.width = width
    iframe.height = height
    iframe.style.border = '0'
    iframe.style.display = 'block'
    iframe.allowTransparency = 'true'

    insertAfter(linkElem, iframe)
  }
  // 处理图片链接
  function processImageLink(linkElem) {
    const match = linkElem.href.match(imageRegex)
    if (match) {
      const imageUrl = match[1]
      createImagePreview(linkElem, imageUrl)
    }
  }
  // 处理嵌入链接
  function processEmbedLink(linkElem) {
    for (let config of embedConfigs) {
      let match
      if (Array.isArray(config.regex)) {
        match = config.regex.some(r => linkElem.href.match(r))
      } else {
        match = linkElem.href.match(config.regex)
      }

      if (match) {
        let embedUrl = config.embedUrl

        if (config.embedUrl.includes('$')) {
          const regex = Array.isArray(config.regex) ? config.regex[0] : config.regex
          const match = linkElem.href.match(regex)
          embedUrl = config.embedUrl.replace(/\$(\d)/g, (s, g) => match[g])
        }

        if (config.name === 'xiaoyuzhou') {
          embedUrl = linkElem.href
        }

        appendEmbedIframe(linkElem, embedUrl, config.width, config.height)

        break
      }
    }
  }
  // 处理所有链接
  function processLink(linkElem) {
    processImageLink(linkElem)
    processEmbedLink(linkElem)
  }
  
  function processAllLinks() {
    document.querySelectorAll('.contentLink').forEach(link => {
      if (!link.hasAttribute('data-processed')) {
        link.setAttribute('data-processed', true)
        processLink(link)
      }
    })
  }

  // 在文档第一次加载完执行

  let initFun = () => {
    let app = document.querySelector('#app')
    if (app) {
      setTimeout(() => {
        processAllLinks()
      }, 1000)
    } else {
      setTimeout(() => {
        initFun()
      }, 500)
    }
  }
  initFun()

  // 在按下回车键时执行
  document.addEventListener('keydown', function (event) {
    processAllLinks()
  })
  document.documentElement.addEventListener('click', function (event) {
    processAllLinks()
  })
})()