Greasy Fork

Greasy Fork is available in English.

workflowy-images-and-bilibili-videos

Embed image links into workflowy

// ==UserScript==
// @name         workflowy-images-and-bilibili-videos
// @namespace    http://tampermonkey.net/
// @version      0.31
// @description  Embed image links into workflowy
// @author       Jonathan Leung (https://github.com/jonleung)&eterlan(https://github.com/eterlan)
// @match        https://workflowy.com/*
// @grant        none
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.1/underscore-min.js
// @license MIT
// ==/UserScript==
"use strict";

// 在脚本最开始的部分,添加这个函数
function addReferrerMeta() {
    const meta = document.createElement('meta');
    meta.name = 'referrer';
    meta.content = 'no-referrer';
    document.head.appendChild(meta);
}

(function() {
    if (document.head) {
        addReferrerMeta();
    } else {
        document.addEventListener('DOMContentLoaded', addReferrerMeta);
    }
})();

var IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp"];

function createImageNodeAfterNode($node, imgSrc) {
  if ($node.parent().find(".content-img").length === 0) {
    var $div = $("<div>").addClass("content-img");
    var $img = $("<img>").attr("src", imgSrc).css({
      "max-width": "100%",
      "max-height": "350px",
    });
    $div.append($img);

    $node.after($div);
  }
}

function generateImagesForContentNode(node) {
  var $node = $(node);

  var text = $node.text();

  var markdownImageRegex = /\!\[.*\]\((.+)\)/;
  var matcher = text.match(markdownImageRegex);
  if (matcher !== null) {
    var imgSrc = matcher[1];
    createImageNodeAfterNode($node, imgSrc);
  }
}

function generateImagesForLinkNode(node) {
  var $node = $(node);
  var href = $node.attr('href');

  // 如果没有 href 属性,直接返回
  if (!href) return;

  var hasImageExtension = IMAGE_EXTENSIONS.some((ext) =>
    href.toLowerCase().endsWith(ext)
  );

  if (hasImageExtension) {
    createImageNodeAfterNode($node.parent().parent(), href);
  }
}

// 添加 B 站视频 ID 提取函数
function getBilibiliVideoId(url) {
  const bvMatch = url.match(/BV\w{10}/);
  return bvMatch ? bvMatch[0] : null;
}

function createBilibiliIframeAfterNode($node, videoId) {
  if ($node.parent().find(".content-video").length === 0) {
    var $div = $("<div>").addClass("content-video");
    var $iframe = $("<iframe>")
      .attr(
        "src",
        `https://player.bilibili.com/player.html?bvid=${videoId}&page=1&autoplay=0`
      )
      .attr("scrolling", "no")
      .attr("border", "0")
      .attr("frameborder", "no")
      .attr("framespacing", "0")
      .attr("allowfullscreen", "true")
      .css({
        width: "100%",
        height: "500px",
        "max-width": "800px",
      });
    $div.append($iframe);
    $node.after($div);
  }
}

function generateVideoForLinkNode(node) {
  var $node = $(node);
  var url = $node.attr('href');

  // 检查是否是 B 站链接
  if (url.includes("bilibili.com/video")) {
    var videoId = getBilibiliVideoId(url);
    if (videoId) {
      createBilibiliIframeAfterNode($node.parent().parent(), videoId);
    }
  }
}

function checkForChanges() {
  // 清理不再需要的图片
  $("div.content-img").each(function (i, imgDiv) {
    var $imgDiv = $(imgDiv);
    var $prevContent = $imgDiv.prev(".content");

    // 检查前一个 content 元素中是否还包含图片链接
    var hasMarkdownImage = $prevContent.text().match(/\!\[.*\]\((.+)\)/);

    // 检查图片链接
    var hasImageLink = false;
    $prevContent.find("a.contentLink").each(function (_, link) {
      var $link = $(link);
      var href = $link.attr('href');
      if (href && IMAGE_EXTENSIONS.some((ext) => href.toLowerCase().endsWith(ext))) {
        hasImageLink = true;
        return false; // break
      }
    });

    // 如果既没有 markdown 图片也没有图片链接,则移除
    if (!hasMarkdownImage && !hasImageLink) {
      $imgDiv.remove();
    }
  });

  // 移除不再有对应链接的视频
  $("div.content-video").each(function (i, videoDiv) {
    var $videoDiv = $(videoDiv);
    var $prevContent = $videoDiv.prev(".content");
    var hasVideoLink = false;

    $prevContent.find("a.contentLink").each(function (_, link) {
      var url = $(link).attr('href');
      if (url.includes("bilibili.com/video")) {
        hasVideoLink = true;
        return false;
      }
    });

    if (!hasVideoLink) {
      $videoDiv.remove();
    }
  });

  // 原有的图片处理逻辑
  $("div.name div.content, div.notes div.content").each(function (i, node) {
    generateImagesForContentNode(node);
  });

  $("div.name a.contentLink, div.notes a.contentLink").each(function (i, node) {
    generateImagesForLinkNode(node);
    generateVideoForLinkNode(node); // 添加视频处理
  });
}

// 添加 MutationObserver 来监听 DOM 变化
const observer = new MutationObserver(function (mutations) {
  checkForChanges();
});

// 当页面加载完成时
$(window).on("load", function () {
  checkForChanges();

  // 开始观察 DOM 变化
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  });

  // 为确保内容加载后能显示图片,额外延迟检查一次
  setTimeout(checkForChanges, 1000);
});

// When you change nodes
window.onhashchange = checkForChanges;

// When you press any keyboard key
$(document).keydown(function (e) {
  setTimeout(function () {
    checkForChanges();
  }, 250);
});