绿皮科技编辑器式反链,慎用

本贴最后更新于 819 天前,其中的信息可能已经时过境迁

通过 hack 的方式实现卡片式超链接 - 链滴 (ld246.com)类似的方式往嵌入块和反链挂 shadowDOM 可以实现绿皮版的编辑器式反链,不过这种就更蛋疼了,对机器性能不是很有信心的话就别尝试了,而且效果也不大好,类似这样

image.png

反正就是嵌入块和反向链接面板能够直接编辑笔记内容了。

代码大概这样,原理跟上面那个差不多,不过因为都是 iframe 插入的移动端界面比较吃性能, 加了个可见性判断,不可见的时候就不加载它了,一样的,试思路的产品, 要实际用的话最好改改哈:

import { DOM监听器 } from "/script/public/DOMwatcher.js";

const hideElements = (panels, protyle) => {
  if (!protyle) {
    if (panels.includes("dialog")) {
      for (let i = 0; i < window.siyuan.dialogs.length; i++) {
        if (window.siyuan.dialogs[i].destroy()) {
          i--;
        }
      }
    }
    return;
  }
  if (panels.includes("hint")) {
    clearTimeout(protyle.hint.timeId);
    protyle.hint.element.classList.add("fn__none");
  }
  if (protyle.gutter && panels.includes("gutter")) {
    protyle.gutter.element.classList.add("fn__none");
    protyle.gutter.element.innerHTML = "";
    // https://ld246.com/article/1651935412480
    protyle.wysiwyg.element
      .querySelectorAll(".protyle-wysiwyg--hl")
      .forEach((item) => {
        item.classList.remove("protyle-wysiwyg--hl");
      });
  }
  if (protyle.toolbar && panels.includes("toolbar")) {
    protyle.toolbar.element.classList.add("fn__none");
  }
  if (protyle.toolbar && panels.includes("util")) {
    const pinElement =
      protyle.toolbar.subElement.querySelector('[data-type="pin"]');
    if (
      !pinElement ||
      (pinElement && !pinElement.classList.contains("ft__primary"))
    ) {
      protyle.toolbar.subElement.classList.add("fn__none");
    }
  }
  if (panels.includes("select")) {
    protyle.wysiwyg.element
      .querySelectorAll(".protyle-wysiwyg--select")
      .forEach((item) => {
        item.classList.remove("protyle-wysiwyg--select");
      });
  }
};
const disabledProtyle = (protyle) => {
  hideElements(["gutter", "toolbar", "select", "hint", "util"], protyle);
  protyle.disabled = true;
  protyle.wysiwyg.element.setAttribute("contenteditable", "false");
  protyle.wysiwyg.element
    .querySelectorAll('[contenteditable="true"][spellcheck="false"]')
    .forEach((item) => {
      item.setAttribute("contenteditable", "false");
    });
};
export class protyleEditor extends naive.plugin {
  constructor() {
    super({ name: "protyleEditor" });

    window.siyuan.ws.ws.addEventListener("message", () => {
      this.hackBacklink();
    });
    document.addEventListener("mouseover", () => {
      this.hackBacklink();
    });
    let 监听选项1 = {
      监听目标: `[data-node-id]`,
      监听器回调: () => this.hackBacklink(),
    };
   
    this.DOM监听器1 = new DOM监听器(监听选项1);

    this.hackBacklink();
    /*shadowDocument.body.appendChild(editorElement)
        let styles=  document.head.querySelectorAll('style')
        styles.forEach(
            style=>{
                let  shadowStyle=style.cloneNode(true)
                shadowDocument.head.appendChild(shadowStyle)
  
            }
        )
        let links =document.head.querySelectorAll('link')
        links.forEach(
            style=>{
                let  shadowStyle=style.cloneNode(true)
                shadowDocument.head.appendChild(shadowStyle)
                if (shadowStyle.getAttribute('href').startsWith('base')){
                    let href= shadowStyle.getAttribute('href')
                    href ='/stage/build/app/'+href
                    shadowStyle.setAttribute('href',href)
                }
            }
        )
        let Protyle =window.siyuan.layout.centerLayout.children[0].children[0].model.editor.__proto__.constructor 
        console.log('protyleEditor',Protyle)
        new Protyle(editorElement, {
            blockId: "20201117101902-2ewjjum",
            hasContext: false,
            action: ["cb-get-all"],
            render: {
                gutter: true,
                breadcrumbDocName: false,
                breadcrumbContext: false
            },
            typewriterMode: false,
            after: (editor) => {
                if (window.siyuan.config.readonly) {
                    disabledProtyle(editor.protyle);
                }
                editorElement.addEventListener("mouseleave", () => {
                    hideElements(["gutter"], editor.protyle);
                });
            }
        });*/
  }
  async hackBacklink() {
    let 目标元素组 = document.querySelectorAll(
      `.backlinkList.fn__flex-1 ul [data-treetype="backlink"] .b3-list-item__text,.backlinkMList.fn__flex-1 ul [data-treetype="backlink"] .b3-list-item__text`
    );
    let 目标元素组1 = document.querySelectorAll(
      ".protyle-wysiwyg__embed:not(.protyle-wysiwyg__embed .protyle-wysiwyg__embed)"
    );
    this.createEditor(目标元素组);
    this.createEditor(目标元素组1);

    //window.requestAnimationFrame(async() => this.hackBacklink())
  }
  createEditor(目标元素组) {
    this.渲染计数器=0
    目标元素组.forEach(async (块元素,i) =>
      setTimeout(() => {
        if (块元素.parentElement.dataset.type == "NodeDocument") {
          this.渲染计数器-=1
          return;
        }
        if (!this.isInViewPort(块元素)) {
          this.渲染计数器-=1
          if(块元素.shadowRoot){
            let element = 块元素.shadowRoot.querySelector("iframe");
            element.setAttribute('src','')
          }
          return;
        }
        if(this.渲染计数器>10){
          return
        }
        this.渲染计数器+=1
        if (!块元素.shadowRoot) {
          块元素.attachShadow({ mode: "open" });
          let editorElement = document.createElement("div");
          let element = document.createElement("iframe");
          element.classList.add(
            "block__popover",
            "block__popover--move",
            "block__popover--top"
          );
          element.setAttribute("loading", 'lazy');

          element.setAttribute("border", 0);
          element.setAttribute("width", "100%");
          element.setAttribute("frameBorder", "none");
          element.setAttribute(
            "src",
            `/stage/build/mobile/?hideToolBar=true&&id=${
              (块元素.dataset && 块元素.dataset.id) ||
              块元素.previousElementSibling.dataset.id
            }`
          );
          editorElement.className = "block__edit  fn__flex-1 protyle";
          块元素.shadowRoot.appendChild(element);
        } else {
          let element = 块元素.shadowRoot.querySelector("iframe");
          if (
            element &&
            element.getAttribute("src") !==
              `/stage/build/mobile/?hideToolBar=true&&id=${
                (块元素.dataset && 块元素.dataset.id) ||
                块元素.previousElementSibling.dataset.id
              }`
          ) {
            element.setAttribute(
              "src",
              `/stage/build/mobile/?hideToolBar=true&&id=${
                (块元素.dataset && 块元素.dataset.id) ||
                块元素.previousElementSibling.dataset.id
              }`
            );
          }
        }
      }, 10)
    );
  }
  isInViewPort(element) {
    const viewWidth = window.innerWidth || document.documentElement.clientWidth;
    const viewHeight =
      window.innerHeight || document.documentElement.clientHeight;
    const { top, right, bottom, left } = element.getBoundingClientRect();
    return top >= -100 && left >= -100 && right <= viewWidth+200 && bottom <= viewHeight+200;
  }
}
export const environments = ["APP"];
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    22381 引用 • 89601 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • 对了 源代码还是依赖我自用的 naive 主题的,所以要在别的地方用的话可能需要稍微改改,不过改动应该也不算大

推荐标签 标签

  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 177 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    287 引用 • 4484 回帖 • 669 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 1 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖 • 2 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    5 引用 • 107 回帖
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 29 关注
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 673 关注
  • 创造

    你创造的作品可能会帮助到很多人,如果是开源项目的话就更赞了!

    179 引用 • 995 回帖 • 1 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖 • 3 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖 • 2 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 609 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 624 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 2 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    85 引用 • 139 回帖
  • 酷鸟浏览器

    安全 · 稳定 · 快速
    为跨境从业人员提供专业的跨境浏览器

    3 引用 • 59 回帖 • 26 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖 • 1 关注
  • 笔记

    好记性不如烂笔头。

    308 引用 • 793 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖 • 1 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 510 关注
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖
  • SEO

    发布对别人有帮助的原创内容是最好的 SEO 方式。

    35 引用 • 200 回帖 • 23 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3453 回帖 • 203 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 431 关注
  • jsDelivr

    jsDelivr 是一个开源的 CDN 服务,可为 npm 包、GitHub 仓库提供免费、快速并且可靠的全球 CDN 加速服务。

    5 引用 • 31 回帖 • 60 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    408 引用 • 3574 回帖 • 2 关注