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

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

通过 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"];
  • 思源笔记

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

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

    22017 引用 • 87794 回帖 • 2 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 631 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖 • 1 关注
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    132 引用 • 188 回帖
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 387 关注
  • 百度

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

    63 引用 • 785 回帖 • 182 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    176 引用 • 815 回帖
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 63 关注
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 53 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • 工具

    子曰:“工欲善其事,必先利其器。”

    285 引用 • 728 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    55 引用 • 85 回帖 • 1 关注
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • Sphinx

    Sphinx 是一个基于 SQL 的全文检索引擎,可以结合 MySQL、PostgreSQL 做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。

    1 引用 • 210 关注
  • CongSec

    本标签主要用于分享网络空间安全专业的学习笔记

    1 引用 • 1 回帖 • 10 关注
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 2 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    46 引用 • 25 回帖
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    5 引用 • 62 回帖
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    107 引用 • 295 回帖
  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    25 引用 • 83 回帖
  • 爬虫

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

    106 引用 • 275 回帖
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 354 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 1 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    497 引用 • 1387 回帖 • 294 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 335 关注
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖 • 1 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    11 引用 • 5 回帖 • 606 关注