Skip to content

Comments

fix: listener triggered when stored marks set#2181

Merged
Saul-Mirone merged 1 commit intoMilkdown:mainfrom
ylc395:fix/event-listener-trigger
Nov 25, 2025
Merged

fix: listener triggered when stored marks set#2181
Saul-Mirone merged 1 commit intoMilkdown:mainfrom
ylc395:fix/event-listener-trigger

Conversation

@ylc395
Copy link
Contributor

@ylc395 ylc395 commented Nov 24, 2025

  • I read the contributing guide
  • I agree to follow the code of conduct

Summary

Event listeners should be triggered when storedMarks changed by transaction.

How did you test this change?

I wrote a plugin like this:

import { $prose } from '@milkdown/kit/utils';
import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
import { Mapping } from '@milkdown/kit/prose/transform';

// 该插件实现:当用户删掉了特殊元素内的所有文本后,该特殊元素也被一并删除。否则用户的后续输入会被视为发生在该特殊元素内,这不符合用户的直觉
// 例子(不符合直觉的情况):用户输入 **aaa**,得到一个 <strong>aaa</strong> 元素,随后用户按3次退格键(删光了aaa),接着又进行输入,这个新输入被标记为 strong
export const deleteEmptyNode = $prose(() => {
  return new Plugin({
    key: new PluginKey('DELETE_EMPTY_NODE'),
    appendTransaction: (transactions, oldState, newState) => {
      if (!transactions.some((tr) => tr.docChanged)) {
        return null;
      }

      if (!newState.selection.empty) return null;

      const mapping = new Mapping(transactions.toReversed().flatMap((tr) => tr.mapping.invert().maps));
      const oldPos = oldState.doc.resolve(mapping.map(newState.selection.$anchor.pos));

      // 前后的内容都是空,这意味着我们在一个空的文本块元素内
      if (!newState.selection.$anchor.nodeBefore && !newState.selection.$anchor.nodeAfter) {
        const { parent } = newState.selection.$anchor;

        // 这个空的块级元素如果只是段落之类的,空着就空着,不管了
        if (!parent.isTextblock || parent.type.name === 'paragraph') {
          return null;
        }

        const oldNode = oldPos.parent;

        // 该块级元素是刚创建出来的,此前并不存在
        if (oldNode.type !== parent.type || oldNode.content.size === 0) {
          return null;
        }

        return newState.tr.setNodeMarkup(newState.selection.$anchor.before(), newState.schema.nodes.paragraph);
      }

      // 行内元素,满足:之前有标记,之后没有标记(或者标记的内容全是空格)
      if (
        oldPos.marks().length > 0 &&
        [newState.selection.$anchor.nodeBefore, newState.selection.$anchor.nodeAfter].every(
          (node) => !node?.marks || node.marks.length === 0 || !node.text?.trim(),
        )
      ) {
        return newState.tr.setStoredMarks(null);
      }
    },
  });
});

When this plugin makes a transaction(newState.tr.setStoredMarks(null)), listeners should be triggered.

@changeset-bot
Copy link

changeset-bot bot commented Nov 24, 2025

⚠️ No Changeset found

Latest commit: a361796

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Nov 24, 2025

@ylc395 is attempting to deploy a commit to the Milkdown Team on Vercel.

A member of the Team first needs to authorize it.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 24, 2025

Open in StackBlitz

@milkdown/components

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/components@2181

@milkdown/core

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/core@2181

@milkdown/crepe

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/crepe@2181

@milkdown/ctx

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/ctx@2181

@milkdown/exception

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/exception@2181

@milkdown/kit

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/kit@2181

@milkdown/prose

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/prose@2181

@milkdown/transformer

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/transformer@2181

@milkdown/utils

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/utils@2181

@milkdown/react

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/react@2181

@milkdown/vue

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/vue@2181

@milkdown/plugin-automd

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-automd@2181

@milkdown/plugin-block

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-block@2181

@milkdown/plugin-clipboard

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-clipboard@2181

@milkdown/plugin-collab

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-collab@2181

@milkdown/plugin-cursor

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-cursor@2181

@milkdown/plugin-emoji

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-emoji@2181

@milkdown/plugin-highlight

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-highlight@2181

@milkdown/plugin-history

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-history@2181

@milkdown/plugin-indent

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-indent@2181

@milkdown/plugin-listener

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-listener@2181

@milkdown/plugin-prism

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-prism@2181

@milkdown/plugin-slash

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-slash@2181

@milkdown/plugin-tooltip

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-tooltip@2181

@milkdown/plugin-trailing

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-trailing@2181

@milkdown/plugin-upload

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/plugin-upload@2181

@milkdown/preset-commonmark

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/preset-commonmark@2181

@milkdown/preset-gfm

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/preset-gfm@2181

@milkdown/theme-nord

npm i https://pkg.pr.new/Milkdown/milkdown/@milkdown/theme-nord@2181

commit: a361796

Copy link
Member

@Saul-Mirone Saul-Mirone left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Saul-Mirone Saul-Mirone added this pull request to the merge queue Nov 25, 2025
Merged via the queue into Milkdown:main with commit d5a3c29 Nov 25, 2025
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants