prosemirror 学习记录(四)decoration

news2024/11/15 14:08:56

使用 decorations

使用 props - decorations() 添加 decorations

写一个简单的插件:高亮所有 apple 节点

export const MyHighlightApplesPlugin = new Plugin({
  props: {
  	// view 每次变化都会执行 decorations 方法
    decorations(state) {
      let arrs = [];
      state.doc.descendants((node, pos) => {
        if (node.type.name === "apple") {
          const deco = Decoration.inline(pos, pos + 1, { class: "highlight" });
          arrs.push(deco);
        }
      });
      return DecorationSet.create(state.doc, arrs);	// 返回 DecorationSet
    },
  },
});

css

span[custom-node-type="apple"].highlight::before {
  background: yellow;
  color: red;
}

效果:

在这里插入图片描述

用 Plugin - state 存储数据

Plugin 中的 state 字段可以存储数据

  • init: (config, state) => T
  • apply: (tr, value:T, oldState, newState) => T

plugin.getState(state) 可以获取这个数据

将 DecorationSet 存在 state 中,改写上面的插件:

export const MyHighlightApplesPlugin = new Plugin({
  state: {
    init(_, state) {
      return createAppleDecos(state.doc);
    },
    apply(tr) {
      return createAppleDecos(tr.doc);
    },
  },
  props: {
    decorations(state) {
      const set = MyHighlightApplesPlugin.getState(state);
      return set;
    },
  },
});

function createAppleDecos(doc) {
  let arrs = [];
  doc.descendants((node, pos) => {
    if (node.type.name === "apple") {
      const deco = Decoration.inline(pos, pos + 1, { class: "highlight" });
      arrs.push(deco);
    }
  });
  return DecorationSet.create(doc, arrs); // 返回 DecorationSet
}

setMeta

给高亮效果添加开关,点击按钮随时切换是否高亮

plugin 中存储 enable 字段(以前只存储 set,现在是 {enable,set}

export const MyHighlightApplesPlugin = new Plugin({
  state: {
    init(_, state) {
      return {
        enable: true,
        set: createAppleDecos(state.doc),
      };
    },
    apply(tr, value) {
      const { enable } = value;
      let set;
      if (enable) {
        set = createAppleDecos(tr.doc);
      } else {
        set = DecorationSet.empty;
      }
      return { enable, set };
    },
  },
  props: {
    decorations(state) {
      const { set } = MyHighlightApplesPlugin.getState(state);
      return set;
    },
  },
});

enable 字段添加上了,接下来要在点击按钮时修改它的值


function toggleHighlightApples() {
  // 通过 getState 获取数据
  const state = MyHighlightApplesPlugin.getState(editorView.value.state);
  // 直接修改!
  state.enable = !state.enable;
  // 然后 dispatch 一个 tr
  const tr = editorView.value.state.tr;
  editorView.value.dispatch(tr);
}

上面的代码在插件外部直接修改 state.enable ,能实现效果,但是不好。
正确的做法是发一个信号,让 plugin 内部自己修改。

tr.setMeta 发信号:

function toggleHighlightApples() {
  const state = MyHighlightApplesPlugin.getState(editorView.value.state);
  const tr = editorView.value.state.tr;
  tr.setMeta(MyHighlightApplesPlugin, !state.enable);
  editorView.value.dispatch(tr);
}

applygetMeta 接收信号

    apply(tr, value) {
      let { enable } = value;
      const meta = tr.getMeta(MyHighlightApplesPlugin);
      if (meta !== undefined) {
        enable = meta;
      }
      let set;
      if (enable) {
        set = createAppleDecos(tr.doc);
      } else {
        set = DecorationSet.empty;
      }
      return { enable, set };
    },

效果

在这里插入图片描述

set.map(tr.mapping, tr.doc) 的作用

官网示例 image placeholder example 中用到 set.map(tr.mapping, tr.doc) ,作用看不懂,写代码测试一下

写一个简单的插件:给粗体文字自动添加红色背景

export const TestPlugin = new Plugin({
  state: {
    init(_, state) {
      return addRedBg(state.doc);
    },
    apply(tr, set) {
      return set;
    },
  },
  props: {
    decorations(state) {
      const set = TestPlugin.getState(state);
      return set;
    },
  },
});

function addRedBg(doc) {
  let arrs = [];
  doc.descendants((node, pos) => {
    if (node.marks.find((mark) => mark.type.name === "strong")) {
      const deco = Decoration.inline(pos, pos + node.nodeSize, { style: "background:red" });
      arrs.push(deco);
    }
  });
  return DecorationSet.create(doc, arrs);
}

文档初始内容为:

<p>你好,今天天气不错。<strong>中午</strong>吃什么</p>

效果:

在这里插入图片描述

因为只在 init 中设置 deco,在 apply 中什么都没做。所以插件不会响应后续视图变化

新增 bold 文本,不会变红:

在这里插入图片描述

移除 bold,不会消失:

在这里插入图片描述

修改文档内容,致使bold文字位置变动,红色不跟着挪位置:

在这里插入图片描述
这些都是意料之中的效果。现在在 apply 中添加上这一句:

    apply(tr, set) {
      set = set.map(tr.mapping, tr.doc);	// 新增
      return set;
    },

新增 bold 文本、移除 bold 的效果不变,不放图了。

修改文档内容,致使bold文字位置变动,效果和之前不同了:

在这里插入图片描述

transform Guide 中讲到了 Mapping 的用法

let tr = new Transform(myDoc)
tr.split(10)    // split a node, +2 tokens at 10
tr.delete(2, 5) // -3 tokens at 2
console.log(tr.mapping.map(15)) // → 14
console.log(tr.mapping.map(6))  // → 3
console.log(tr.mapping.map(10)) // → 9

结合 DecorationSet.map 的说明:
在这里插入图片描述
set.map(tr.mapping, tr.doc) 的含义就明白了 —— 所有 deco 都应用 tr.mapping 找到新位置。

但是对于新增的 bold 文本(需要新增 deco),或者已经有的 bold 文本去掉 bold 效果(需要移除 deco),set.map(tr.mapping, tr.doc) 就无能为力了(剪切、复制、拖拽等同样处理不了)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1135201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux常用命令——chsh命令

在线Linux命令查询工具 chsh 用来更换登录系统时使用的shell 补充说明 chsh命令用来更换登录系统时使用的shell。若不指定任何参数与用户名称&#xff0c;则chsh会以应答的方式进行设置。 语法 chsh(选项)(参数)选项 -s<shell 名称>或--shell<shell 名称>&a…

【QT开发笔记-基础篇】| 第四章 事件QEvent | 4.10 总结QT中的事件传递流程

本节对应的视频讲解&#xff1a;B_站_链_接 【QT开发笔记-基础篇】 第4章 事件 4.10 总结事件传递流程(1) 事件处理函数接受还是忽略 本章要实现的整体效果如下&#xff1a; 事件传递总流程图&#xff0c;如下&#xff1a; 这张图是不是还不太明白&#xff1f;&#xff1f; 别…

《CS2》隆重登场,艾尔莎EA H610M-I和你征战新版本

作为电竞游戏的常青树&#xff0c;《反恐精英》的热门程度可以说是经久不衰。虽然《反恐精英》已经迭代了许多个版本&#xff0c;但是上一次大版本更新已经是2012年的《CS:GO》了。最近&#xff0c;V社正式上线了全新的《CS2》&#xff0c;它是由Source2引擎所开发&#xff0c;…

Nat. Methods | 哈佛李恒组开发三代HiFi宏基因组组装软件--hifiasm-meta

使用hifiasm-meta进行Hifi长读宏基因组序列组装 Metagenome assembly of high-fidelity long reads with hifiasm-meta Article&#xff0c;2022-05-09 Nature methods, [IF 48] DOI&#xff1a;https://doi.org/10.1038/s41592-022-01478-3 原文链接&#xff1a;https://www.n…

全连接=可编程!玻色量子成功研制光量子测控一体机——“量枢”

近日&#xff0c;北京玻色量子科技有限公司成功完成了光量子测控一体机——“量枢”的研制&#xff0c;作为一款光量子信号测量反馈控制设备&#xff0c;它是专门为相干光量子计算机定制的一套集光量子测量反馈、系统状态检测、计算流程控制等功能于一身的智能系统。 玻色量子自…

腾讯联手警方重拳出击,平阳警方斩断特大外挂黑色产业链

近期&#xff0c;在闲游盒腾讯守护者计划安全团队的协助下&#xff0c;平阳警方成功破获一起特大《绝地求生》外挂案件。捣毁了一个集外挂作者、卡盟平台、一级代理销售商、二级代理销售商等多个环节为一体的网络黑色产业链&#xff0c;共抓捕34名犯罪嫌疑人。 2018年5月初&…

什么是React中的context(上下文)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

electron27+react18集成搭建跨平台应用|electron窗口多开

基于Electron27集成React18创建一个桌面端exe程序。 electron27-vite4-react18基于electron27结合vite4构建工具快速创建react18跨端应用实践。 版本列表 "vite": "^4.4.5" "react": "^18.2.0" "electron": "^27.0.1&…

51单片机的PWM控制呼吸灯

文章目录 前言一、PWM引脚以及寄存器的配置二、呼吸灯逻辑总结 前言 hello 大家好这里是夏目学长的51单片机课堂&#xff0c;本篇博客是夏目学长观看B站up主学电超人的视频所写的一篇51单片机入门博客之51单片机PWM配置呼吸灯 &#xff0c;我自己在学习这节课程的时候觉得这节…

【MySQL--->内置函数】

文章目录 [TOC](文章目录) 一、日期函数二、字符串函数三、数学函数四、其他函数 一、日期函数 current_date();当前日期 current_time();当前时间 current_timestamp();当前时间戳 now();当前时间 date(‘date’);日期 date_sub(date,interval number second/minute/hour/d…

18.2 使用NPCAP库抓取数据包

NPCAP 库是一种用于在Windows平台上进行网络数据包捕获和分析的库。它是WinPcap库的一个分支&#xff0c;由Nmap开发团队开发&#xff0c;并在Nmap软件中使用。与WinPcap一样&#xff0c;NPCAP库提供了一些API&#xff0c;使开发人员可以轻松地在其应用程序中捕获和处理网络数据…

基于PyTorch的MNIST手写体分类实战

第2章对MNIST数据做了介绍&#xff0c;描述了其构成方式及其数据的特征和标签的含义等。了解这些有助于编写合适的程序来对MNIST数据集进行分析和识别。本节将使用同样的数据集完成对其进行分类的任务。 3.1.1 数据图像的获取与标签的说明 MNIST数据集的详细介绍在第2章中已…

基于springboot实现就业信息管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现就业信息管理系统演示 摘要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;就业信息管理系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人…

最新Unity DOTS教程之BlobAsset核心机制分析

最近DOTS发布了正式的版本, 我们来分享一下DOTS里面BlobAsset机制&#xff0c;方便大家上手学习掌握Unity DOTS开发。 BlobAsset 概叙 DOTS提供了BlobAsset机制来把数据生成高效的二进制数据。BlobAsset的数据是不可变的。BlobAsset只支持非托管类型数据。支持Burst编译器编译…

计时的vue写法

<el-input type"text" id"timetext" value"00时00分00秒" readonly></el-input> <el-button type"button" click"start()">开始</el-button> <el-button type"button" click"st…

用Visual Studio(VS)开发UNIX/Linux项目

目录 FTP是免不了的 正确设置头文件 组织项目结构 创建何种项目类型 FTP自动上传 大部分具有Windows开发经验的程序员会比较喜欢使用Visual Studio&#xff0c;而大部分Unix/Linux程序员则喜欢使用UltraEdit直接在主机上写代码。 为什么直接在主机上写代码呢&#xff0c;因…

软考系列(系统架构师)- 2015年系统架构师软考案例分析考点

试题一 软件架构&#xff08;质量属性效用树、架构风险、依够点、权衡点&#xff09; 【问题1】&#xff08;12分&#xff09; 在架构评估过程中&#xff0c;质量属性效用树&#xff08;utility tree&#xff09;是对系统质量属性进行识别和优先级排序的重要工具。请给出合适的…

第20章 Netty

20.1 说说IO的交互流程 难度:★ 重点:★ 白话解析 这道题主要是用来帮助理解后面题目的,IO交互主要分为两种:本地IO和网络IO。 1、本地IO:数据在磁盘上,通过系统调用read()方法读取数据到内核空间的缓冲区,然后再读取到 用户空间的缓冲区,这就是IO的交互过程。 2、网…

华为---DHCP中继代理简介及示例配置

DHCP中继代理简介 IP动态获取过程中&#xff0c;客户端&#xff08;DHCP Client&#xff09;总是以广播&#xff08;广播帧及广播IP报文&#xff09;方式来发送DHCPDISCOVER和DHCPREQUEST消息的。如果服务器&#xff08;DHCP Server&#xff09;和 客户端不在同一个二层网络(二…

【100天精通Python】Day71:Python可视化_一文掌握Seaborn库的使用《一》_数据分布可视化,数据关系可视化,示例+代码

目录 1. 数据分布的可视化 1.1 直方图&#xff08;Histograms&#xff09; 1.2 核密度估计图&#xff08;Kernel Density Estimation Plot&#xff09; 1.3 箱线图&#xff08;Box Plot&#xff09; 1.4 小提琴图&#xff08;Violin Plot&#xff09; ​编辑1.5 散点图&am…