From ed5e126f3e337ef5de83618474b8036d04bdc6cb Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Thu, 9 Jul 2026 15:16:23 +0000 Subject: [PATCH 1/6] feat(comments): add Presets.comments for comment undo/redo Track comment create, remove, edit and drag via optional preset wired to comment-plugin signals. DragCommentAction stores position and links from commentdragged for atomic undo/redo. Fixes #40 Co-authored-by: Cursor --- package-lock.json | 41 ++++++- package.json | 9 +- rete.config.ts | 3 +- src/index.ts | 1 + src/presets/comments/actions/comment.ts | 135 ++++++++++++++++++++++++ src/presets/comments/index.ts | 128 ++++++++++++++++++++++ src/presets/index.ts | 1 + tsconfig.json | 7 +- 8 files changed, 318 insertions(+), 7 deletions(-) create mode 100644 src/presets/comments/actions/comment.ts create mode 100644 src/presets/comments/index.ts diff --git a/package-lock.json b/package-lock.json index de08c8b..aa06089 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,11 +16,39 @@ "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", "rete-cli": "~2.0.1", + "rete-comment-plugin": "file:../comment-plugin", "typescript": "~4.8.4" }, "peerDependencies": { "rete": "^2.0.1", - "rete-area-plugin": "^2.0.0" + "rete-area-plugin": "^2.0.0", + "rete-comment-plugin": "^2.1.0" + }, + "peerDependenciesMeta": { + "rete-comment-plugin": { + "optional": true + } + } + }, + "../comment-plugin": { + "name": "rete-comment-plugin", + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "devDependencies": { + "globals": "^15.9.0", + "rete": "^2.0.1", + "rete-area-plugin": "^2.1.5", + "rete-cli": "~2.0.1", + "rollup-plugin-sass": "1.12.17", + "typescript": "4.8.4" + }, + "peerDependencies": { + "rete": "^2.0.1", + "rete-area-plugin": "^2.1.5" } }, "node_modules/@ampproject/remapping": { @@ -6432,10 +6460,11 @@ } }, "node_modules/rete-area-plugin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rete-area-plugin/-/rete-area-plugin-2.1.0.tgz", - "integrity": "sha512-xiqCaxh6AHh9oS2p/gJuI7c3bW4mHj8KsT41jYrvH+b7aZ5DKnxdfq10EFQbfdTwK+kgZiCMM2jVzBQ8Qju2Dg==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rete-area-plugin/-/rete-area-plugin-2.3.2.tgz", + "integrity": "sha512-s7OrCz6xNwVl8EaJ7tXnJVQD9nbd+JAnf82qx/UDweRV86Q1qj2+nT8XkD5m1gSnvSZQqTlMptSiWUrouTEO+w==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -6501,6 +6530,10 @@ "node": ">=14.17" } }, + "node_modules/rete-comment-plugin": { + "resolved": "../comment-plugin", + "link": true + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", diff --git a/package.json b/package.json index 1ec1065..66918a2 100644 --- a/package.json +++ b/package.json @@ -25,12 +25,19 @@ }, "peerDependencies": { "rete": "^2.0.1", - "rete-area-plugin": "^2.0.0" + "rete-area-plugin": "^2.0.0", + "rete-comment-plugin": "^2.1.0" + }, + "peerDependenciesMeta": { + "rete-comment-plugin": { + "optional": true + } }, "devDependencies": { "globals": "^15.9.0", "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", + "rete-comment-plugin": "^2.1.2", "rete-cli": "~2.0.1", "typescript": "~4.8.4" }, diff --git a/rete.config.ts b/rete.config.ts index 0ed9fe7..3e3c5a4 100644 --- a/rete.config.ts +++ b/rete.config.ts @@ -6,6 +6,7 @@ export default { name: 'ReteHistoryPlugin', globals: { 'rete': 'Rete', - 'rete-area-plugin': 'ReteAreaPlugin' + 'rete-area-plugin': 'ReteAreaPlugin', + 'rete-comment-plugin': 'ReteCommentPlugin' } } diff --git a/src/index.ts b/src/index.ts index f5938b9..db820b5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ export type { Action as HistoryAction } export * as HistoryExtensions from './extensions' export * as Presets from './presets' export type { HistoryActions } from './presets/classic' +export type { CommentHistoryActions } from './presets/comments' export type { Preset } from './presets/types' /** diff --git a/src/presets/comments/actions/comment.ts b/src/presets/comments/actions/comment.ts new file mode 100644 index 0000000..f9d5154 --- /dev/null +++ b/src/presets/comments/actions/comment.ts @@ -0,0 +1,135 @@ +import { Comment, CommentPlugin, FrameComment } from 'rete-comment-plugin' + +import { Action } from '../../../types' + +export type CommentSnapshot = { + id: string + text: string + x: number + y: number + width: number + height: number + links: string[] + kind: 'inline' | 'frame' +} + +type Position = { x: number, y: number } + +function snapshot(comment: Comment): CommentSnapshot { + return { + id: comment.id, + text: comment.text, + x: comment.x, + y: comment.y, + width: comment.width, + height: comment.height, + links: [...comment.links], + kind: comment instanceof FrameComment + ? 'frame' + : 'inline' + } +} + +export class AddCommentAction implements Action { + private stored?: CommentSnapshot + + constructor( + private comment: CommentPlugin, + private commentId: string + ) { } + + undo() { + const item = this.comment.comments.get(this.commentId) + + if (!item) return + + this.stored = snapshot(item) + this.comment.delete(this.commentId) + } + + redo() { + if (!this.stored) return + + this.comment.restoreComment(this.stored) + } +} + +export class RemoveCommentAction implements Action { + constructor( + private comment: CommentPlugin, + private stored: CommentSnapshot + ) { } + + undo() { + this.comment.restoreComment(this.stored) + } + + redo() { + this.comment.delete(this.stored.id) + } +} + +export class DragCommentAction implements Action { + prev: Position + new: Position + prevLinks: string[] + newLinks: string[] + + constructor( + private comment: CommentPlugin, + public commentId: string, + prev: Position, + current: Position, + prevLinks: string[], + newLinks: string[] + ) { + this.prev = { ...prev } + this.new = { ...current } + this.prevLinks = [...prevLinks] + this.newLinks = [...newLinks] + } + + private async moveTo(position: Position, links: string[]) { + const item = this.comment.comments.get(this.commentId) + + if (!item) return + + await this.comment.translate(this.commentId, position.x - item.x, position.y - item.y) + item.linkTo([...links]) + } + + async undo() { + await this.moveTo(this.prev, this.prevLinks) + } + + async redo() { + await this.moveTo(this.new, this.newLinks) + } +} + +export class EditCommentAction implements Action { + constructor( + private comment: CommentPlugin, + private commentId: string, + private previousText: string, + private newText: string + ) { } + + undo() { + const item = this.comment.comments.get(this.commentId) + + if (!item) return + + item.text = this.previousText + item.update() + } + + redo() { + const item = this.comment.comments.get(this.commentId) + + if (!item) return + + item.text = this.newText + item.update() + } +} diff --git a/src/presets/comments/index.ts b/src/presets/comments/index.ts new file mode 100644 index 0000000..e299cfe --- /dev/null +++ b/src/presets/comments/index.ts @@ -0,0 +1,128 @@ +import { CommentPlugin, FrameComment } from 'rete-comment-plugin' + +import { HistoryPlugin } from '../..' +import { Preset } from '../types' +import { + AddCommentAction, + CommentSnapshot, + DragCommentAction, + EditCommentAction, + RemoveCommentAction +} from './actions/comment' + +export type { CommentSnapshot } from './actions/comment' +export { + AddCommentAction, + DragCommentAction, + EditCommentAction, + RemoveCommentAction +} + +export type CommentHistoryActions = + | AddCommentAction + | RemoveCommentAction + | DragCommentAction + | EditCommentAction + +function toSnapshot(data: { id: string, text: string, x: number, y: number, width: number, height: number, links: string[] }): CommentSnapshot { + return { + id: data.id, + text: data.text, + x: data.x, + y: data.y, + width: data.width, + height: data.height, + links: [...data.links], + kind: data instanceof FrameComment + ? 'frame' + : 'inline' + } +} + +function sameLinks(a: string[], b: string[]) { + return a.length === b.length && a.every((value, index) => value === b[index]) +} + +function trackCreated( + history: HistoryPlugin, + comment: CommentPlugin +) { + comment.addPipe(context => { + if (context.type === 'commentcreated') { + history.add(new AddCommentAction(comment, context.data.id)) + } + return context + }) +} + +function trackRemoved( + history: HistoryPlugin, + comment: CommentPlugin +) { + comment.addPipe(context => { + if (context.type === 'commentremoved') { + history.add(new RemoveCommentAction(comment, toSnapshot(context.data))) + } + return context + }) +} + +function trackEdited( + history: HistoryPlugin, + comment: CommentPlugin +) { + comment.addPipe(context => { + if (context.type === 'commentedited') { + const { comment: item, previousText } = context.data + + history.add(new EditCommentAction(comment, item.id, previousText, item.text)) + } + return context + }) +} + +function trackDragged( + history: HistoryPlugin, + comment: CommentPlugin +) { + comment.addPipe(context => { + if (context.type !== 'commentdragged') return context + + const { id, previous, links } = context.data + const item = comment.comments.get(id) + + if (!item) return context + + const moved = previous.x !== item.x || previous.y !== item.y + const relinked = !sameLinks(links.prev, links.next) + + if (moved || relinked) { + history.add(new DragCommentAction( + comment, + id, + previous, + { x: item.x, y: item.y }, + links.prev, + links.next + )) + } + + return context + }) +} + +/** + * Comments preset for the history plugin. Tracks comment add/remove/drag/edit. + */ +export function setup(props: { + comment: CommentPlugin +}): Preset { + return { + connect(history) { + trackCreated(history, props.comment) + trackRemoved(history, props.comment) + trackEdited(history, props.comment) + trackDragged(history, props.comment) + } + } +} diff --git a/src/presets/index.ts b/src/presets/index.ts index 20d6ab0..ff1c6d3 100644 --- a/src/presets/index.ts +++ b/src/presets/index.ts @@ -4,3 +4,4 @@ */ export * as classic from './classic' +export * as comments from './comments' diff --git a/tsconfig.json b/tsconfig.json index 108617b..30fca4a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,9 @@ { "extends": "rete-cli/configs/tsconfig.json", - "include": ["src"] + "include": ["src"], + "compilerOptions": { + "paths": { + "rete-comment-plugin": ["../comment-plugin/src/index.ts"] + } + } } From 6ac175e95e74de6782ed5aeffb11326e85c173bb Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Thu, 9 Jul 2026 18:46:16 +0000 Subject: [PATCH 2/6] feat(comments): frame membership undo and slim commentdragged handling Add NodeFrameMembershipAction, History.removeRecent for drag coalescing, and derive frame node snapshots from area when handling prevLinks-only commentdragged. Bump to 2.2.0 with comment-plugin ^2.2.0 peer. Co-authored-by: Cursor --- package-lock.json | 12 +-- package.json | 6 +- src/history.ts | 16 +++ src/index.ts | 7 ++ src/presets/comments/actions/comment.ts | 122 ++++++++++++++++++---- src/presets/comments/index.ts | 128 +++++++++++++++++++----- 6 files changed, 241 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa06089..628a6bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rete-history-plugin", - "version": "2.1.1", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rete-history-plugin", - "version": "2.1.1", + "version": "2.2.0", "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0" @@ -16,13 +16,13 @@ "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", "rete-cli": "~2.0.1", - "rete-comment-plugin": "file:../comment-plugin", + "rete-comment-plugin": "^2.2.0", "typescript": "~4.8.4" }, "peerDependencies": { "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", - "rete-comment-plugin": "^2.1.0" + "rete-comment-plugin": "^2.2.0" }, "peerDependenciesMeta": { "rete-comment-plugin": { @@ -32,7 +32,7 @@ }, "../comment-plugin": { "name": "rete-comment-plugin", - "version": "2.1.2", + "version": "2.2.0", "dev": true, "license": "MIT", "dependencies": { @@ -42,7 +42,7 @@ "globals": "^15.9.0", "rete": "^2.0.1", "rete-area-plugin": "^2.1.5", - "rete-cli": "~2.0.1", + "rete-cli": "~2.0.2", "rollup-plugin-sass": "1.12.17", "typescript": "4.8.4" }, diff --git a/package.json b/package.json index 66918a2..d96cdad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rete-history-plugin", - "version": "2.1.1", + "version": "2.2.0", "description": "", "scripts": { "build": "rete build -c rete.config.ts", @@ -26,7 +26,7 @@ "peerDependencies": { "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", - "rete-comment-plugin": "^2.1.0" + "rete-comment-plugin": "^2.2.0" }, "peerDependenciesMeta": { "rete-comment-plugin": { @@ -37,8 +37,8 @@ "globals": "^15.9.0", "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", - "rete-comment-plugin": "^2.1.2", "rete-cli": "~2.0.1", + "rete-comment-plugin": "^2.2.0", "typescript": "~4.8.4" }, "dependencies": { diff --git a/src/history.ts b/src/history.ts index d387ab0..e0c1e16 100644 --- a/src/history.ts +++ b/src/history.ts @@ -35,6 +35,22 @@ export default class History { return list } + removeRecent(predicate: (record: HistoryRecord) => boolean, ms: number) { + const treshold = Date.now() - ms + + for (let i = this.produced.length - 1; i >= 0; i--) { + const record = this.produced[i] + + if (record.time <= treshold) break + if (record.separated) break + + if (predicate(record)) { + this.produced.splice(i, 1) + return record + } + } + } + async move(from: HistoryRecord[], to: HistoryRecord[], type: 'undo' | 'redo') { const record = from.pop() diff --git a/src/index.ts b/src/index.ts index db820b5..bf73963 100644 --- a/src/index.ts +++ b/src/index.ts @@ -86,6 +86,13 @@ export class HistoryPlugin boolean, ms?: number) { + return this.history.removeRecent(predicate, ms ?? this.timing * 2) + } + /** * Clear history */ diff --git a/src/presets/comments/actions/comment.ts b/src/presets/comments/actions/comment.ts index f9d5154..b72879d 100644 --- a/src/presets/comments/actions/comment.ts +++ b/src/presets/comments/actions/comment.ts @@ -1,21 +1,24 @@ -import { Comment, CommentPlugin, FrameComment } from 'rete-comment-plugin' +import { BaseSchemes, NodeId } from 'rete' +import { BaseAreaPlugin } from 'rete-area-plugin' +import { + Comment, + CommentPlugin, + CommentRestoreData, + FrameBounds, + FrameComment +} from 'rete-comment-plugin' import { Action } from '../../../types' -export type CommentSnapshot = { - id: string - text: string - x: number - y: number - width: number - height: number - links: string[] - kind: 'inline' | 'frame' -} +export type CommentSnapshot = CommentRestoreData + +export type FrameState = FrameBounds & { links: string[] } type Position = { x: number, y: number } -function snapshot(comment: Comment): CommentSnapshot { +type LinkedNodeSnapshot = { id: string, prev: Position, new: Position } + +export function commentSnapshot(comment: Comment): CommentSnapshot { return { id: comment.id, text: comment.text, @@ -43,7 +46,7 @@ export class AddCommentAction implements Action { if (!item) return - this.stored = snapshot(item) + this.stored = commentSnapshot(item) this.comment.delete(this.commentId) } @@ -74,36 +77,119 @@ export class DragCommentAction implements Action { new: Position prevLinks: string[] newLinks: string[] + private prevFrame?: FrameState + private newFrame?: FrameState + private nodes: LinkedNodeSnapshot[] constructor( private comment: CommentPlugin, + private area: BaseAreaPlugin, public commentId: string, prev: Position, current: Position, prevLinks: string[], - newLinks: string[] + newLinks: string[], + nodes?: { id: string, previous: Position, current: Position }[] ) { this.prev = { ...prev } this.new = { ...current } this.prevLinks = [...prevLinks] this.newLinks = [...newLinks] + this.nodes = (nodes ?? []).map(({ id, previous, current: next }) => ({ + id, + prev: { ...previous }, + new: { ...next } + })) + + const item = comment.comments.get(commentId) + + // Frame drag changes position only; bounds stay until membership/resize elsewhere + if (item instanceof FrameComment) { + this.prevFrame = { + x: prev.x, + y: prev.y, + width: item.width, + height: item.height, + links: [...prevLinks] + } + this.newFrame = { + x: item.x, + y: item.y, + width: item.width, + height: item.height, + links: [...newLinks] + } + } } - private async moveTo(position: Position, links: string[]) { + private async applyInline(position: Position, links: string[]) { const item = this.comment.comments.get(this.commentId) if (!item) return await this.comment.translate(this.commentId, position.x - item.x, position.y - item.y) - item.linkTo([...links]) + await this.comment.setCommentLinks(this.commentId, links) + } + + private async applyFrame(frame: FrameState, nodeTarget: 'prev' | 'new') { + this.comment.setFrameState(this.commentId, frame) + + for (const node of this.nodes) { + const position = nodeTarget === 'prev' + ? node.prev + : node.new + const view = this.area.nodeViews.get(node.id) + + if (view) await view.translate(position.x, position.y) + } + } + + async undo() { + if (this.prevFrame) { + await this.applyFrame(this.prevFrame, 'prev') + return + } + + await this.applyInline(this.prev, this.prevLinks) + } + + async redo() { + if (this.newFrame) { + await this.applyFrame(this.newFrame, 'new') + return + } + + await this.applyInline(this.new, this.newLinks) } +} + +export class NodeFrameMembershipAction implements Action { + constructor( + private comment: CommentPlugin, + private frames: { + id: string + prev: FrameState + next: FrameState + }[], + private node: { id: NodeId, prev: Position, new: Position } | null + ) { } async undo() { - await this.moveTo(this.prev, this.prevLinks) + await this.comment.restoreNodeFrameMembership({ + frames: this.frames.map(frame => ({ id: frame.id, state: frame.prev })), + ...this.node + ? { node: { id: this.node.id, position: this.node.prev } } + : {} + }) } async redo() { - await this.moveTo(this.new, this.newLinks) + await this.comment.restoreNodeFrameMembership({ + frames: this.frames.map(frame => ({ id: frame.id, state: frame.next })), + ...this.node + ? { node: { id: this.node.id, position: this.node.new } } + : {} + }) } } diff --git a/src/presets/comments/index.ts b/src/presets/comments/index.ts index e299cfe..239586e 100644 --- a/src/presets/comments/index.ts +++ b/src/presets/comments/index.ts @@ -1,20 +1,27 @@ -import { CommentPlugin, FrameComment } from 'rete-comment-plugin' +import { BaseSchemes } from 'rete' +import { BaseAreaPlugin } from 'rete-area-plugin' +import { CommentPlugin, FrameComment, FrameMembership } from 'rete-comment-plugin' import { HistoryPlugin } from '../..' +import { DragNodeAction } from '../classic/actions/node' import { Preset } from '../types' import { AddCommentAction, - CommentSnapshot, + commentSnapshot, DragCommentAction, EditCommentAction, + FrameState, + NodeFrameMembershipAction, RemoveCommentAction } from './actions/comment' -export type { CommentSnapshot } from './actions/comment' +export type { CommentSnapshot, FrameState } from './actions/comment' export { AddCommentAction, + commentSnapshot, DragCommentAction, EditCommentAction, + NodeFrameMembershipAction, RemoveCommentAction } @@ -22,25 +29,54 @@ export type CommentHistoryActions = | AddCommentAction | RemoveCommentAction | DragCommentAction + | NodeFrameMembershipAction | EditCommentAction -function toSnapshot(data: { id: string, text: string, x: number, y: number, width: number, height: number, links: string[] }): CommentSnapshot { +function toFrameState(bounds: FrameMembership['previous'], links: string[]): FrameState { return { - id: data.id, - text: data.text, - x: data.x, - y: data.y, - width: data.width, - height: data.height, - links: [...data.links], - kind: data instanceof FrameComment - ? 'frame' - : 'inline' + x: bounds.x, + y: bounds.y, + width: bounds.width, + height: bounds.height, + links: [...links] } } -function sameLinks(a: string[], b: string[]) { - return a.length === b.length && a.every((value, index) => value === b[index]) +type Position = { x: number, y: number } + +function frameDragNodes( + item: FrameComment, + previous: Position, + area: BaseAreaPlugin +) { + const dx = item.x - previous.x + const dy = item.y - previous.y + + return item.links + .map(id => { + const view = area.nodeViews.get(id) + + if (!view) return null + + return { + id, + previous: { x: view.position.x - dx, y: view.position.y - dy }, + current: { ...view.position } + } + }) + .filter((node): node is { id: string, previous: Position, current: Position } => Boolean(node)) +} + +function absorbAllDragNodeActions( + history: HistoryPlugin, + nodeId: string, + timing: number +) { + while (history.removeRecent(record => { + const action = record.action + + return action instanceof DragNodeAction && action.nodeId === nodeId + }, timing)) { /* remove recent classic drag actions for the same node */ } } function trackCreated( @@ -61,7 +97,7 @@ function trackRemoved( ) { comment.addPipe(context => { if (context.type === 'commentremoved') { - history.add(new RemoveCommentAction(comment, toSnapshot(context.data))) + history.add(new RemoveCommentAction(comment, commentSnapshot(context.data))) } return context }) @@ -83,27 +119,36 @@ function trackEdited( function trackDragged( history: HistoryPlugin, - comment: CommentPlugin + comment: CommentPlugin, + area: BaseAreaPlugin ) { comment.addPipe(context => { if (context.type !== 'commentdragged') return context - const { id, previous, links } = context.data + const { id, previous, prevLinks } = context.data const item = comment.comments.get(id) if (!item) return context + const newLinks = [...item.links] const moved = previous.x !== item.x || previous.y !== item.y - const relinked = !sameLinks(links.prev, links.next) + const relinked = prevLinks.length !== newLinks.length + || prevLinks.some((linkId: string, index: number) => linkId !== newLinks[index]) if (moved || relinked) { + const nodes = item instanceof FrameComment + ? frameDragNodes(item, previous, area) + : [] + history.add(new DragCommentAction( comment, + area, id, previous, { x: item.x, y: item.y }, - links.prev, - links.next + prevLinks, + newLinks, + nodes )) } @@ -111,18 +156,55 @@ function trackDragged( }) } +function trackMembershipChanged( + history: HistoryPlugin, + comment: CommentPlugin, + timing: number +) { + comment.addPipe(context => { + if (context.type !== 'commentmembershipchanged') return context + + const { node, frames } = context.data + + if (node) absorbAllDragNodeActions(history, node.id, timing) + + const nodeSnapshot = node + ? { id: node.id, prev: node.previous, new: node.current } + : null + + history.add(new NodeFrameMembershipAction( + comment, + frames.map((frame: FrameMembership) => ({ + id: frame.id, + prev: toFrameState(frame.previous, frame.links.prev), + next: toFrameState(frame.current, frame.links.next) + })), + nodeSnapshot + )) + + return context + }) +} + /** * Comments preset for the history plugin. Tracks comment add/remove/drag/edit. + * + * Register together with `Presets.classic.setup()` so node drags that change frame + * membership replace the classic `DragNodeAction` with `NodeFrameMembershipAction`. */ export function setup(props: { comment: CommentPlugin }): Preset { return { connect(history) { + const area = history.parentScope>(BaseAreaPlugin) + const timing = history.timing * 2 + trackCreated(history, props.comment) trackRemoved(history, props.comment) trackEdited(history, props.comment) - trackDragged(history, props.comment) + trackDragged(history, props.comment, area) + trackMembershipChanged(history, props.comment, timing) } } } From b175ab0d08d1d331de2c84f14153a152918a94a1 Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Thu, 9 Jul 2026 19:13:52 +0000 Subject: [PATCH 3/6] chore(comments): pin comment-plugin dev dep to dist branch Install rete-comment-plugin from github dist/feature/comments-history until 2.2.0 is on npm, so CI can resolve the comments preset types. Co-authored-by: Cursor --- package-lock.json | 36 ++++++++++++------------------------ package.json | 2 +- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 628a6bf..b4a48e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", "rete-cli": "~2.0.1", - "rete-comment-plugin": "^2.2.0", + "rete-comment-plugin": "github:retejs/comment-plugin#dist/feature/comments-history", "typescript": "~4.8.4" }, "peerDependencies": { @@ -30,27 +30,6 @@ } } }, - "../comment-plugin": { - "name": "rete-comment-plugin", - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "devDependencies": { - "globals": "^15.9.0", - "rete": "^2.0.1", - "rete-area-plugin": "^2.1.5", - "rete-cli": "~2.0.2", - "rollup-plugin-sass": "1.12.17", - "typescript": "4.8.4" - }, - "peerDependencies": { - "rete": "^2.0.1", - "rete-area-plugin": "^2.1.5" - } - }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -6531,8 +6510,17 @@ } }, "node_modules/rete-comment-plugin": { - "resolved": "../comment-plugin", - "link": true + "version": "2.1.3", + "resolved": "git+ssh://git@github.com/retejs/comment-plugin.git#3ee35210b31afe8b7eaf593e05f3e6fa8c58c1e7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "peerDependencies": { + "rete": "^2.0.1", + "rete-area-plugin": "^2.1.5" + } }, "node_modules/reusify": { "version": "1.0.4", diff --git a/package.json b/package.json index d96cdad..1356190 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", "rete-cli": "~2.0.1", - "rete-comment-plugin": "^2.2.0", + "rete-comment-plugin": "github:retejs/comment-plugin#dist/feature/comments-history", "typescript": "~4.8.4" }, "dependencies": { From 55dcd3ee0aa1dad9fbb2431acddc7e2895ee6a27 Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Thu, 9 Jul 2026 19:27:29 +0000 Subject: [PATCH 4/6] chore: remove external tsconfig path for comment-plugin Resolve rete-comment-plugin via devDependency only; do not map module paths outside the repository. Co-authored-by: Cursor --- tsconfig.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 30fca4a..108617b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,4 @@ { "extends": "rete-cli/configs/tsconfig.json", - "include": ["src"], - "compilerOptions": { - "paths": { - "rete-comment-plugin": ["../comment-plugin/src/index.ts"] - } - } + "include": ["src"] } From 51cac1c3efb79a86b37e9470f94324cb5046cbc3 Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Thu, 9 Jul 2026 22:54:39 +0000 Subject: [PATCH 5/6] fix(comments): align comment-plugin peer range with 2.1.3 Co-authored-by: Cursor --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1356190..888859c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "peerDependencies": { "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", - "rete-comment-plugin": "^2.2.0" + "rete-comment-plugin": "^2.1.3" }, "peerDependenciesMeta": { "rete-comment-plugin": { From fdf64c46c51f951f4999dc4c324b0c2e9b7b6eb7 Mon Sep 17 00:00:00 2001 From: Ni55aN Date: Fri, 10 Jul 2026 15:54:22 +0000 Subject: [PATCH 6/6] build(deps): use published rete-comment-plugin ^2.2.0 Replace the temporary git dist dependency after comment-plugin release. Co-authored-by: Cursor --- package-lock.json | 7 ++++--- package.json | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4a48e5..dfe0d84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", "rete-cli": "~2.0.1", - "rete-comment-plugin": "github:retejs/comment-plugin#dist/feature/comments-history", + "rete-comment-plugin": "^2.2.0", "typescript": "~4.8.4" }, "peerDependencies": { @@ -6510,8 +6510,9 @@ } }, "node_modules/rete-comment-plugin": { - "version": "2.1.3", - "resolved": "git+ssh://git@github.com/retejs/comment-plugin.git#3ee35210b31afe8b7eaf593e05f3e6fa8c58c1e7", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/rete-comment-plugin/-/rete-comment-plugin-2.2.0.tgz", + "integrity": "sha512-jrC52O5tCaHPI/IGximliy9Pv0NEZnWoJkEQ2/aaYNg9Cv6XvhmMy8tSExUM3CFhYbgNpzeRYywhffm5wJ7DlA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 888859c..d96cdad 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "peerDependencies": { "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", - "rete-comment-plugin": "^2.1.3" + "rete-comment-plugin": "^2.2.0" }, "peerDependenciesMeta": { "rete-comment-plugin": { @@ -38,7 +38,7 @@ "rete": "^2.0.1", "rete-area-plugin": "^2.0.0", "rete-cli": "~2.0.1", - "rete-comment-plugin": "github:retejs/comment-plugin#dist/feature/comments-history", + "rete-comment-plugin": "^2.2.0", "typescript": "~4.8.4" }, "dependencies": {